你不知道的javascript笔记

this

函数中的this并不指向函数本身,即不是在函数定义时所在的词法作用域中,而是指向函数运行时所在作用域。this的指向规则有四种:

  1. new绑定,将this绑定到new出来的实例对象上。
  2. 显示绑定this,使用apply或者call将this绑定到指定对象上面
  3. 隐式绑定this。
  4. 默认绑定this,在非严格模式下this绑定到全局对象,严格模式下this绑定到undefined。

new

1
2
3
4
5
function foo() {
console.log(this.a);
}
var a = 2;
foo(); // 2

apply和call

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function foo(a, b) {
console.log(this.a + a + b);
}
var obj = {
a: 1,
foo: foo
}
foo.apply(obj, ['hello', 'world']);
function bar(a, b) {
console.log(a, b);
}
// apply给null对象,用于数组转序列参数的传递
bar.apply(null, ['hello', 'world']);
// ES6直接使用扩展运算符将数组转成参数序列
bar(...['hello', 'world']);

隐式绑定

1
2
3
4
5
6
7
8
function foo() {
console.log(this.a);
}
var obj = {
a: 1,
foo: foo
}
obj.foo(); // 1 this绑定到obj

默认绑定

1
2
3
4
5
function foo() {
console.log(this.a);
}
var a = 1;
foo(); // 1

优先级

new > apply > 隐式绑定 > 默认绑定

判断this

现在我们可以根据优先级来判断函数在某个调用位置应用的是哪条规则。可以按照下面的顺序来进行判断:

1
2
3
4
5
6
7
function foo() {
this.a = 2;
}
var obj1 = {
foo: foo
}
var obj2 = {};
  1. 函数是否在new中调用(new绑定)?如果是的话this绑定的是新创建的对象。
    var bar = new foo(), bar.a === 2
  2. 函数是否通过call、apply(显式绑定)或者硬绑定调用?如果是的话,this绑定的是 指定的对象。
    var bar = foo.call(obj2), obj2.a === 2
  3. 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this 绑定的是那个上 下文对象。
    var bar = obj1.foo(), obj1.a === 2
  4. 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到 全局对象。
    var bar = foo(), global.a === 2
如果您觉得受益了,欢迎打赏鼓励。