1、对 this 对象的理解
this 是执行上下文中的一个属性,它指向最后一次调用这个方法的对象。在实际开发中,this 的指向可以通过四种调用模式来判断。
1.1、this 指向有四种绑定规则
- 默认绑定规则:在全局当中指向 window;独立调用也指向 window
- 隐式绑定规则:谁调用就指向谁
- 显式绑定规则:call、bind、apply
- new 绑定(构造器调用模式) 优先级: new绑定 > 显式绑定规则 > 隐式绑定规则 > 默认绑定规则
1.2、默认绑定规则
在全局中:
console.log(this === window); // true
在函数中:
function test() {
console.log(this === window);
}
// 函数的独立调用:
test(); // true
window.test(); // true
1.3、隐式绑定规则
每个函数在执行的时候就会有自身的一个this指向,可能值相同,但他们是不同的;也可以这么说:如果一个函数作为一个对象的方法来调用时,this 指向这个对象。
例子1:
var a = 0;
var obj = {
a: 2,
foo: function() {
console.log(this); -> 指向 obj
function test() {
console.log(this); -> 指向 window
}
test(); -> 这里是独立调用
}
}
obj.foo(); -> 这里是 obj 调用
打印:
例子2:
// 在浏览器环境,只要是立即执行函数 -> 相当于独立调用,指向全都是 window;
// 还需分 node 环境,模块化环境,严格模式环境
(function() {
console.log(this) -> 指向 window
})()
例子3: 闭包:当函数执行时,导致函数被定义,并被抛出
var obj = {
a: 2,
foo: function() { // 函数执行
console.log(this); -> 指向 obj
// 这就是闭包:
function test() { // 被定义
console.log(this); -> 指向 window
}
return test; // 抛出
}
}
obj.foo()(); -> 这里第二个()是为了执行 test()
例子4: 变量赋值的情况
var a = 0;
function foo() {
console.log(this);
}
var obj = {
a: 2;
foo: foo;
}
obj.foo() -> 指向 obj
var bar = obj.foo;
// 完成赋值后,bar 已经和 obj 没有任何联系,给了一个 foo 函数,但没有执行
bar();
// 函数在此执行,在 window 下执行,为全局 -> this指向window
例子5:
参数赋值的情况
var a = 0;
function foo() {
console.log(this); -> 指向 window
}
function bar(fn) {
fn(); -> 独立调用
fn.call(obj); -> 指向 obj
}
var obj = {
a: 2, foo: foo;
}
bar(obj.foo)
1.4、显式绑定规则:call、bind、apply
1.4.1、 call() 和 apply() 的区别 \
它们的作用一模一样,区别仅在于传入参数的形式的不同。
- apply 接受两个参数,第一个参数指定了函数体内 this 对象的指向,第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组,apply 方法把这个集合中的元素作为参数传递给被调用的函数。
- call 传入的参数数量不固定,跟 apply 相同的是,第一个参数也是代表函数体内的 this 指向,从第二个参数开始往后,每个参数被依次传入函数。