JS 作用域 闭包 this 原型 知识点总结

如果你能看懂以下两张图, 那就可以跳过本总结了, 当然, 点个赞再走啊喂! (#`O′)!


啊喂分割线 (#`O′)! (#`O′)! (#`O′)! (#`O′)! (#`O′)! (#`O′)! (#`O′)! (#`O′)! (#`O′)! 

你不知道的JavaScript(上册)

作用域和闭包

  1. LHS和RHS查询, 可以理解为查找变量赋值的目标和源头, 当然, "赋值"可以是隐晦的
  2. LHS查询失败, 将在严格模式下导致抛出RefrenceError, 非严格模式下则会自动创建新变量
  3. eval额with分别是修改原有作用域和根据参数创建一个新的作用域
  4. 我们如果把函数理解成代码片段之间的接口?
  5. for循环中的var会污染上级作用域 -> var会污染上级作用域 -> js(es5)没有块级作用域? -> 通过IIFE可以伪装一个块级作用域(但这种方法并不普适), 其实with和catch可以创建一个块级作用域 -> js(es5)有块级作用域, 更别说es6了
  6. 某个函数拥有上级(或上多级)作用域的引用, 就叫做闭包, 详细一点说明就是: 当函数记住并访问其所在的词法作用域, 即便它是在当前词法作用域之外执行, 这就产生了闭包. 闭包可以使得函数就访问定义时的词法作用域, 实际上只要使用了回调函数就使用了闭包
  7. 模块的两个主要特征: 为创建内部作用域而封装了包装函数; 包装函数的返回值必须包括一个内部函数的引用;
  8. JS只有词法作用域(定义在书写代码使得作用域, 当然排除eval和with)
  9. 词法作用域关注函数在何处声名, 动态作用域关注函数在何处调用
  10. bind函数经常用于替代匿名的箭头函数, 以创建具名函数

this和对象原型

  1. 想比较于显式传入上下文对象, this关键字使用了一种更佳优雅的方式, 传递一个对象的引用
  2. this不指向(或不仅仅指向)函数本身或者函数的作用域, 他是在函数创建(调用)时被绑定的
  3. 在非严格模式中, 直接调用函数, 通常会自动将this绑定到全局对象, 称之默认绑定
  4. 隐式绑定即判断调用函数时的上下文对象, 如 obj.say(), 将say中的this隐式绑定到obj
  5. 显式绑定即call, apply, 其中一种特殊的形式叫做硬绑定, bind
  6. 使用new将会发生如下步骤: 创建新对象, 设置__proto__为函数的prototype, 绑定this到新对象, 默认返回这个新对象(最后这一点常被认为是new的一个副作用)
  7. 给bing, call等函数传入null, undefined将出乎意料的导致this绑定到全局对象, 更安全的解决办法是使用一个空对象, 如Object.create(null)
  8. JS中基本类型本身不是对象, 只是创建时字面量会自动被转化为对象, typeof null === 'object' 的结果是bug
  9. 对象键访问会将其中的值转化为字符串, 就算是数字也不例外, 然而数组反之
  10. 通过遍历对象属性进行freeze可以模拟"深度冻结", 但是可能在无意中冻结其它(共享)对象
  11. hasOwnProperty只检查自身属性, 而in操作符会搜索至原型链
  12. 4 in [1,2,4] 可能不会得到你想要的结果 --- 答案是false, 因为in操作符检查的是属性名
  13. 类/继承描述了代码的一种组织结构方式->软件对真实世界问题领域的建模方法
  14. 多态指父类的通用行为可以被子类用更特殊的行为重写
  15. JS中利用显示伪多态(Car子类调用Vehicle.drive.call(this)), 将极大增加维护成本, 代码复杂度, 应尽量避免使用, 或者改为将父类方法保存到子类中
  16. 总的来说, 在JS中模拟类是得不偿失的
  17. 属性的屏蔽比想象中的要复杂, 如果底层对象没有该属性, 则上层对象的属性的writable:false或是其作为setter存在, 会对赋值(=)操作有影响, 当然你可以使用defineProperty来解除这种影响. 这里有个坑, 如a.b++其实相当于a.b=a.b+1
  18. 继承意味着"复制操作", JS中通过prototype实现的继承, 将只是创建对象之间的关联, 而不是复制操作
  19. JS中"构造函数"的概念仅存在于使用new操作符时, new将普通函数劫持, 将调用变成有返回值的"构造函数调用"
  20. JS中.constructor属性与"构造"毫无关系, 把他当成一个普通的属性理解就好
  21. JS原型继承(B.prototype= Object.create(A.prototype))可以类比为"类的继承"
  22. Object.create修改[[Prototype]]以修改对象之间的连接关系, 这和new是一样的, 但是, new还会通过Base.call(newObj)做一些其他事
  23. 空的对象(__proto__==null)叫做"字典", 因为没有任何委托, 所以适合用来储存数据
  24. 总的来说, 用"委托"来描述JS对象之间的关联关系(OLOO)更合适(而不是"复制")
  25. 类风格代码(Function,new或是ES6的Class)强调实体和实体的关系, OLOO则只关注对象关联关系, 这里有两张图太棒了, 可惜放不出来
  26. 鸭子类型(if(a.b)a.b())有时比instanceof有效

你可能感兴趣的:(javascript,作用域,闭包,this,原型)