js小黄书总结
2021-01-05 14:11
253 查看
js 的编译与执行
- 编译阶段:编译器、作用域 源代码 -> 静态地词法分析生层词法作用域 -> 语法分析生成AST -> 将AST转换为可执行代码
- 执行:js引擎,作用域 执行时,js引擎沿着作用域链进行LHS与RHS,知道全局作用于,若仍未发现,则自动创建该全局变量(非严格模式下)。
js严格模式有何不同?
- 禁止隐式或自动创建全局变量
- eval无法改变所在的词法作用域
- js全局作用域的执行上下文不会默认绑定到全局对象上
- 对对象的只读数据进行写操作时,会报错。而不会静默失败。
- 无法为undefined赋值
使用函数的优势?函数有什么用?
- 隐藏内部实现,实现封装的效果
- 减少命名冲突
- 保证局部作用域中的undefined的真实性
js匿名函数的缺点
- 可读性变差
- 调用栈中无法根据函数名进行追踪debug
- 递归不够方便,只能使用过期的argument.callee(已被弃用)进行引用
js中的块级作用域举例:
- with
- try...catch 的 catch () 作用域中
- let
- const
什么是闭包?
- 当函数能够记住并访问所在的词法作用域时,就产生了闭包。
- 以自执行函数为例,产生闭包并不是一定就使用了闭包。
- 严格来讲,只要存在函数嵌套即会产生闭包。只不过这个闭包可能很快就被销毁。而我们常说的闭包,多为长期占用堆内存的闭包。
使用闭包的场景?
定时器、事件监听器、ajax、跨窗口通信、webworkers等,凡是使用了回调函数的地方,就会使用闭包。
改变this指向的几种方法:
- 对象挂载 p85
- 隐式绑定 p86
- call、apply
- bind 硬绑定
- new 绑定
将数组展开成参数的几种方法:
- apply() p97
function foo(a, b) { console.log("a:" + a + ", b:" + b); } // 我们的 DMZ 空对象 var ø = Object.create( null ); // 把数组展开成参数 foo.apply( ø, [2, 3] ); // a:2, b:3 // 使用 bind(..) 进行柯里化
- es6 ...
实现new关键字
function newKeyword (constructor, ...param) { let obj = {}; let proto = Object.create(constructor.prototype); Object.setPrototypeOf(obj, proto); // obj.__proto__ = proto 在浏览器端存在兼容性问题 proto.constructor = constructor; constructor.apply(obj, param); return obj; } function Baby (name, age) { this.name = name; this.age = age; this.show = function () { console.log('我是小柚子'); } } let baby = newKeyword(Baby, 'pomelo', 1)
js数字
- 标注为IEEE754
- 使用64位二进制表示,第一位表示符号位,中间11位表示指数位,最后52位表示小数位。所以可以表示为 1.x 乘以2的y次方,可表示的数值范围是 -2的53次方到2的53次方减一
- 数字的位运算使用32位
##布尔转换
- 假值: undefined、null、0, -0, NaN、''
- 隐式转换为假值:new String(''), new Boolean(false), new Number(0)
new String('') && 1
== 与 === 的区别
- == 在比较时允许使用隐式强制转换,而 === 不允许。
x == y
- x或y都不是null 或undefined时, 且 x,y为除了symbol以外的基础类型, 当在隐式转换时会最终转换为 Number
- x或y存在一个为null或undefined时,只有 null == undefined 为 true
- x或y存在一个为对象时, 调用对象的toPrimitive方法(toString、valueOf)
x < y
- x,y 存在一个为数字,则隐式转换为数字
- x, y 都不是数字,则隐式转换为字符串,并按照字符串顺序比较
运算符的优先级
- && > || > ?> :
回调函数的弊端
- 回到地狱,可读性差,调试困难
- 控制翻转,安全性降低,回调函数的调用情况不受控制
promise的问题
- 在链式调用的最后进行catch时候,不太容易对显示reject的某个promise进行追溯。
- 决议的单一值,在传送多值时,通过对象的封装与解封,会带来一部分开销。即使是使用...,即使是用起来优雅。
- 相较回调的解决方案,肯定会有额外的性能开销。
优化浏览器堵塞的几种思路
- web worker
通过时间差来计算js执行性能的局限性?
- js的执行精度可能无法满足,例如老的IE浏览器,精度仅为15ms
- 执行环境的不确定性,例如:是否受其他因素影响
- 多次执行,总时间除以循环次数,这种方式本身就不够科学,即无法保证测试时每次的执行环境与发布环境下均为一致。
- 多次执行时,js引擎本身就会根据变量的使用频率进行优化,因此会导致结果不够科学严谨。
如何测试?需要注意什么?
- 利用第三方测试库 ,如:benchmark.js
- 尽可能保证测试环境的真实性,跨平台实机测试,以及不同的浏览器内核。利用jsPerf,持续搜集性能数据
- 测试代码应尽可能地真实,不同测试用例的相同逻辑应尽可能保持一致
js代码优化的技巧
- 尾调用栈帧优化(尤其是递归),尽可能使用尾调用。
es6 自定义结构赋值
let test = {}; let target = {name: 'tate', age: 18}; ({name: test.a, age: test.b} = target); console.log(test)
let o = { a: 1, b: 2, c: 3 } let d,e,f, tate; tate = {a: d, b:e, c: f} = o; console.log(tate)
标签模板字面量
function tpl (tpl, val) { console.log(tpl, val) } let name = 'tate'; tpl `my name is ${name}`;
什么情况下,可以将普通函数替换成箭头函数?p130
- 函数内部没有进行任何this的调用
- 函数的调用环境始终与函数所在的词法作用域一致
- 函数中使用了arguments 并且,arguments依赖于父层函数
es6 正则新增模式
- u模式, y模式
unicode 编码方式
- utf-8 变长, 使用1-6个字节表示,兼容ascii
- utf-16 既有定长,又有变长,2个字节或四个字节,js使用utf-16编码
- utf-32 固定四个字节
无法被 Proxy 捕获的行为:
- typeof obj
- String(obj)
- obj + ""
- obj == proxyObj
- obj === proxyObj
相关文章推荐
- IE 和Firefox的js兼容性总结
- js中setTimeout和setInterval性能详解总结
- [提高总结一]js面向对象
- JS常见面试试题总结【去重、遍历、闭包、继承等】
- JS正则表达式+---贪婪和非贪婪模式学习总结
- js基础知识点总结
- 总结几个常用js中操作数组的函数,slice、splice、map等等
- JS数组的操作总结
- js调用后台,后台调用前台等方法总结
- 总结下一些技巧性js代码
- JS事件响应的学习总结
- js数组操作方法总结
- 手机图片预览插件photoswipe.js使用总结
- 总结js开发中的问题
- js总结
- jQuery.cookie.js使用方法总结
- 【Java EE 学习 25 下】【网上图书商城js小技术点总结】
- 原生JS的对象常用操作总结
- 用原生JS读写CSS样式的方法总结
- iOS下JS与原生OC互相调用(总结)