如果你能看懂以下两张图, 那就可以跳过本总结了, 当然, 点个赞再走啊喂! (#`O′)!
啊喂分割线 (#`O′)! (#`O′)! (#`O′)! (#`O′)! (#`O′)! (#`O′)! (#`O′)! (#`O′)! (#`O′)!
你不知道的JavaScript(上册)
作用域和闭包
- LHS和RHS查询, 可以理解为查找变量赋值的目标和源头, 当然, "赋值"可以是隐晦的
- LHS查询失败, 将在严格模式下导致抛出RefrenceError, 非严格模式下则会自动创建新变量
- eval额with分别是修改原有作用域和根据参数创建一个新的作用域
- 我们如果把函数理解成代码片段之间的接口?
- for循环中的var会污染上级作用域 -> var会污染上级作用域 -> js(es5)没有块级作用域? -> 通过IIFE可以伪装一个块级作用域(但这种方法并不普适), 其实with和catch可以创建一个块级作用域 -> js(es5)有块级作用域, 更别说es6了
- 某个函数拥有上级(或上多级)作用域的引用, 就叫做闭包, 详细一点说明就是: 当函数记住并访问其所在的词法作用域, 即便它是在当前词法作用域之外执行, 这就产生了闭包. 闭包可以使得函数就访问定义时的词法作用域, 实际上只要使用了回调函数就使用了闭包
- 模块的两个主要特征: 为创建内部作用域而封装了包装函数; 包装函数的返回值必须包括一个内部函数的引用;
- JS只有词法作用域(定义在书写代码使得作用域, 当然排除eval和with)
- 词法作用域关注函数在何处声名, 动态作用域关注函数在何处调用
- bind函数经常用于替代匿名的箭头函数, 以创建具名函数
this和对象原型
- 想比较于显式传入上下文对象, this关键字使用了一种更佳优雅的方式, 传递一个对象的引用
- this不指向(或不仅仅指向)函数本身或者函数的作用域, 他是在函数创建(调用)时被绑定的
- 在非严格模式中, 直接调用函数, 通常会自动将this绑定到全局对象, 称之默认绑定
- 隐式绑定即判断调用函数时的上下文对象, 如 obj.say(), 将say中的this隐式绑定到obj
- 显式绑定即call, apply, 其中一种特殊的形式叫做硬绑定, bind
- 使用new将会发生如下步骤: 创建新对象, 设置__proto__为函数的prototype, 绑定this到新对象, 默认返回这个新对象(最后这一点常被认为是new的一个副作用)
- 给bing, call等函数传入null, undefined将出乎意料的导致this绑定到全局对象, 更安全的解决办法是使用一个空对象, 如Object.create(null)
- JS中基本类型本身不是对象, 只是创建时字面量会自动被转化为对象, typeof null === 'object' 的结果是bug
- 对象键访问会将其中的值转化为字符串, 就算是数字也不例外, 然而数组反之
- 通过遍历对象属性进行freeze可以模拟"深度冻结", 但是可能在无意中冻结其它(共享)对象
- hasOwnProperty只检查自身属性, 而in操作符会搜索至原型链
- 4 in [1,2,4] 可能不会得到你想要的结果 --- 答案是false, 因为in操作符检查的是属性名
- 类/继承描述了代码的一种组织结构方式->软件对真实世界问题领域的建模方法
- 多态指父类的通用行为可以被子类用更特殊的行为重写
- JS中利用显示伪多态(Car子类调用Vehicle.drive.call(this)), 将极大增加维护成本, 代码复杂度, 应尽量避免使用, 或者改为将父类方法保存到子类中
- 总的来说, 在JS中模拟类是得不偿失的
- 属性的屏蔽比想象中的要复杂, 如果底层对象没有该属性, 则上层对象的属性的writable:false或是其作为setter存在, 会对赋值(=)操作有影响, 当然你可以使用defineProperty来解除这种影响. 这里有个坑, 如a.b++其实相当于a.b=a.b+1
- 继承意味着"复制操作", JS中通过prototype实现的继承, 将只是创建对象之间的关联, 而不是复制操作
- JS中"构造函数"的概念仅存在于使用new操作符时, new将普通函数劫持, 将调用变成有返回值的"构造函数调用"
- JS中.constructor属性与"构造"毫无关系, 把他当成一个普通的属性理解就好
- JS原型继承(B.prototype= Object.create(A.prototype))可以类比为"类的继承"
- Object.create修改[[Prototype]]以修改对象之间的连接关系, 这和new是一样的, 但是, new还会通过Base.call(newObj)做一些其他事
- 空的对象(__proto__==null)叫做"字典", 因为没有任何委托, 所以适合用来储存数据
- 总的来说, 用"委托"来描述JS对象之间的关联关系(OLOO)更合适(而不是"复制")
- 类风格代码(Function,new或是ES6的Class)强调实体和实体的关系, OLOO则只关注对象关联关系, 这里有两张图太棒了, 可惜放不出来
- 鸭子类型(if(a.b)a.b())有时比instanceof有效
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。