《你不知道的JavaScript》(上)阅读总结

83 阅读4分钟

第一部分:作用域与闭包

词法作用域

考虑以下代码

function foo(a){
  var b = a * 2;
  function bar(c) {
    console.log(a, b, c);
  }
  bar(b * 3)
}

在这个例子中有三个逐级嵌套的作用域。

  1. 在这个例子中有三个逐级嵌套的作用域。
  2. 包含着foo所创建的作用域,其中有三个标识符:a、bar和b。
  3. 包含着bar所创建的作用域,其中只有一个标识符:c。

作用域查找会在找到第一个匹配的标识符时停止。在多层的嵌套作用域中可以定义同名的标识符,这叫作“遮蔽效应”(内部的标识符“遮蔽”了外部的标识符)。抛开遮蔽效应,作用域查找始终从运行时所处的最内部作用域开始,逐级向外或者说向上进行,直到遇见第一个匹配的标识符为止。

可以通过eval和with欺骗词法,但一般不推荐使用,防止出现预期之外的错误。

函数作用域

考虑下面的代码:

function foo(a) {
  var b = 2;
  // 一些代码
  function bar() {
    // ...
  }
  // 更多的代码
  var c = 3;
}

在这个代码片段中,foo(..)的作用域气泡中包含了标识符a、b、c和bar。无论标识符声明出现在作用域中的何处,这个标识符所代表的变量或函数都将附属于所处作用域的气泡。

如果function是声明中的第一个词,那么就是一个函数声明,否则就是一个函数表达式。

提升

拥抱新标准,以后编码时尽量使用let和const,避免使用var。因此也就不用考虑变量提升的问题了。

作用域闭包

闭包的定义其实很简单:函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么函数 B 就是闭包。

function A() {
  let a = 1
  window.B = function () {
    console.log(a)
  }
}
A()
B() // 1

很多人对于闭包的解释可能是函数嵌套了函数,然后返回一个函数。其实这个解释是不完整的。

无论通过何种手段将内部函数传递到所在的词法作用域以外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包。


第二部分:this和原型对象

老道在《JavaScript悟道》里说this是糟粕,在代码里出现有时候会让人感到莫名其妙,心烦意乱。黄宝书又说攻克了这道坎,可以让你的代码更加简洁,不必再使用丑陋的代码。鉴于学习过程中this用的还是挺多的,我还是建议来攻克它吧,加油!书其实写的挺好的,有时间还是建议翻翻,当然最好是看作者在github开源的英文第二版的了。

消除对this的错误认知

  1. 指向自身
  2. 它的作用域

学习this的第一步是明白this既不指向函数自身也不指向函数的词法作用域,抛开以前错误的假设和理解。

this是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。

this

function foo() {
  console.log(this.a)
}
var a = 1;
foo()
  const obj = {
  a: 2,
  foo: foo
}
obj.foo()
const c = new foo();
  • 对于直接调用 foo 来说,不管 foo 函数被放在了什么地方, this 一定是 window
  • 对于 obj.foo() 来说,我们只需要记住,谁调用了函数,谁就是 this ,所以在这个场景下 foo 函数中的this 就是 obj 对象
  • 对于 new 的方式来说, this 被永远绑定在了 c 上面,不会被任何方式改变 this

优先级

1.函数是否通过call、apply(显式绑定)或者硬绑定调用?如果是的话,this绑定的是指定的对象。

var bar = new foo()

2.函数是否通过call、apply(显式绑定)或者硬绑定调用?如果是的话,this绑定的是指定的对象。

var bar = foo.call(obj2)

3.函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this绑定的是那个上下文对象。

var bar = obj1.foo()

4.如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到全局对象。

var bar = foo()

剩余

对象可以说是老生常谈了,class类是ES6新增内容,也挺好懂的。

行为委托的话,我jquery和Ajax都学艺不精,也就没有跑源码了。不过也算懂个七七八八了,但要说点什么却说不了。


总结

也不能说不知道吧,但是这些内容确实是不看都不知道自己不会的,多多总结,多敲代码。