每个函数在执行时都有自己的this指向
1. 默认绑定规则:
- 全局中,this指向window
this === window
- 函数的独立调用,this默认指向window (不要把独立调用理解成window调用)
// 函数在全局中调用,也就是被window调用
function test(){console.log(this === window) // true
}
test() // window.test()
2. 隐式绑定规则(对象调用)
- 通过对象的属性来调用方法时,this指向对象(谁调用指向谁)
var a = 0;
var obj = {a: 2,foo: function () {console.log(this) // 1. 指向objfunction test() {console.log(this) // 2. 指向windowconsole.log(test.caller) // 3. foo匿名函数}test() // 2. 函数独立调用// 4. test声明,test调用,就是IIFE; (function () {console.log(this) // window 5. 直接写IIFE})()}
}
obj.foo()
var a = 0
function foo() {console.log(this)
}
var obj = {a: 2,foo: foo
}
obj.foo() // obj 隐式绑定规则
var bar = obj.foo // 隐式丢失:方法被重新赋值
bar() // window 独立调用
- 参数赋值
预编译的过程中,实参被赋值为形参(值的拷贝过程:浅拷贝)
var a = 0
function foo() {console.log(this)
}
function bar(fn){ // bar是高阶函数fn()fn.bind(obj)() // 指向obj// 父函数有能力决定子函数this的指向
}
var obj = {a: 2,foo: foo
}
bar(obj.foo) // window 独立调用
- 数组方法等
var arr = [1]
// forEach还有第二个参数,this指向!!,不传默认是this
arr.forEach(function () {console.log(this) // window
})
arr.forEach(() => {console.log(this) // window
})
function test() {console.log(this)
}
// 不够好的方式
arr.forEach(test.bind(arr)) // arr
// 正确的做法
arr.forEach(function () {console.log(this) // arr
}, arr)
// 不要使用箭头函数+第二个参数改变this指向
arr.forEach(() => {console.log(this) // window
}, arr)
// setInterval(() => {
// console.log(this) // window
// }, 1);
- 例子
var name = '222'
var a = {name: '111',say: function () {console.log(this.name)}
}
var fun = a.say;
fun(); // 222 独立调用
a.say(); // 111 对象调用
FnName.caller并不能用来检测是否是window调用的函数
返回调用指定函数的函数.
如果一个函数f是在全局作用域内被调用的,则f.caller为null,相反,如果一个函数是在另外一个函数作用域内被调用的,则f.caller指向调用它的那个函数.
2.* IIFE内的this指向window(浏览器中/非严格模式)
- 不考虑node中
3. 显示绑定 call、apply、bind
-
bar.call(obj,1,2,3,4,5)
-
bar.apply(obj,[1,2,3,4,5])
-
bar.bind(obj)(1,2,3,4,5)
-
当参数为原始值时,会包装,this指向对应的包装类
-
当参数为null、undefined,this指向window
-
IIFE + 显示绑定(显示绑定优先级 >> IIFE)
var obj = {a: 1
}; (function () {console.log(this) // obj}).call(obj)
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
返回一个原函数的拷贝,并拥有指定的 this 值和初始参数。
const module = {x: 42,getX: function() {return this.x;}
};const unboundGetX = module.getX;
console.log(unboundGetX());
// The function gets invoked at the global scope
// expected output: undefinedconst boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42
bind返回值和原函数不相等,返回一个新函数
const module = {x: 42,getX
};
function getX(){return this.x;
}const boundGetX = module.getX.bind(module);
console.log(boundGetX)
console.log(boundGetX())
console.log(boundGetX === getX); // false
4. new 绑定(优先级 >> 显示绑定)
function Person() {this.a = 'a'console.log(this) // Person实例 {a: 'a'}return {a: 'hhh'}
}
var p = new Person()
console.log(p) // 普通对象{a: 'hhh'}
6. 闭包中
var a = 'a';
var obj = {a: 2,foo: function () {var c = 'c'console.log(this) // objfunction test() {console.log(this) // 3. windowconsole.log(c) // cconsole.log(a) // a(全局上的)console.log(obj) // 能访问}return test // 1. test是闭包// 当函数执行时,导致函数被定义,并抛出}
}
obj.foo()() // 2. test() 独立调用