1.this的绑定类型
1.1 规则一:默认绑定
独立函数调用时(
fn()),this都指向window。跟函数定义的位置没有关系
案例一
function foo() {
console.log(this)
}
foo()//window
案例二
function foo1() {
console.log(this)
}
function foo2() {
console.log(this)
foo1()
}
function foo3() {
console.log(this)
foo2()
}
foo3()//window window window
案例三
var obj = {
name: "CLF",
foo: function() {
console.log(this)
}
}
var bar = obj.foo
bar() // window
1.2 规则二:隐式绑定
通过某个对象发起的函数调用(
obj.fn)
案例一:
var obj = {
name: "CLF",
foo: foo
}
obj.foo() // obj对象
案例二:
var obj1 = {
name: "obj1",
foo: function() {
console.log(this)
}
}
var obj2 = {
name: "obj2",
bar: obj1.foo
}
obj2.bar() //obj对象
1.3 规则三:显式绑定call/apply/bind
bind的优先级高于call和apply。
call和apply在执行函数时,是可以明确的绑定this, 这个绑定规则称之为显示绑定
function foo() {
console.log("函数被调用了", this)
}
var obj = {
name: "obj"
}
foo.call(obj) //obj
foo.apply(obj) //obj
foo.apply("aaaa") //"aaaa"
call和apply的区别:
如果函数需要传入参数,call是直接传入参数,而apply是以数组形式传入参数
function sum(num1, num2, num3) {
console.log(num1 + num2 + num3, this)
}
sum.call("call", 20, 30, 40)
sum.apply("apply", [20, 30, 40])
我们可以使用bind,将一个函数总是显示的绑定到一个对象上
我们发现newFoo()和默认绑定规则冲突,根据结果可以得到:bind显示绑定优先级高于默认绑定
var newFoo = foo.bind("aaa")
newFoo() //'aaa'
1.4 规则四:new绑定
JavaScript中的函数可以当做一个类的构造函数来使用,也就是使用
new关键字
我们通过一个new关键字调用一个函数时(构造器), 这个时候this是在调用这个构造器时创建出来的对象
使用new关键字来调用函数时,会执行如下的操作:
1.创建一个全新的对象;
2.这个新对象会被执行prototype连接;
3.这个新对象会绑定到函数调用的this上(this的绑定在这个步骤完成);
4.如果函数没有返回其他对象,表达式会返回这个新对象;
function Person(name, age) {
this.name = name
this.age = age
}
var p1 = new Person("CLF", 18)
console.log(p1.name, p1.age) //CLF 18
var p2 = new Person("kobe", 30)
console.log(p2.name, p2.age) //kobe 30
2.绑定规则优先级
总结:new绑定 > 显示绑定(call/apply/bind)>隐式绑定(obj.foo())> 默认绑定(foo())
- 默认绑定优先级最低
- call/apply的显示绑定高于隐式绑定
obj.foo.call("abc") //abc
obj.foo.apply("abc") //abc
- bind的显示绑定高于隐式绑定
function foo(){
console.log(this)
}
var obj = {
foo:foo.bind('aaa')
}
obj.foo() //'aaa'
- new关键字高于显示绑定(new不能和call/apply共用)
function foo(){
console.log(this)
}
var bar = foo.bind('aaa')
var obj = new bar() //foo()
3.this规则之外
3.1忽略显示绑定
- 忽略显示绑定:apply/call/bind当传入null或者undefined时,自动将this指向window
foo.apply(null) //window
foo.apply(undefined) //window
3.2间接函数引用
- 间接函数引用:注意obj2的分号必须加,否则会因为代码编译报错
var obj1 = {
name: "obj1",
foo: function() {
console.log(this)
}
}
var obj2 = {
name: "obj2"
};
(obj2.bar = obj1.foo)() //window
4.this的其他补充
4.1.setTimeout的this
function hySetTimeout(fn, duration) {
fn.call("abc")
}
hySetTimeout(function() {
console.log(this) // window
}, 3000)
setTimeout(function() {
console.log(this) // window
}, 2000)
4.2.监听点击事件的this
const boxDiv = document.querySelector('.box')
boxDiv.onclick = function() {
console.log(this) //<div class='box'></div>
}
boxDiv.addEventListener('click', function() {
console.log(this) //<div class='box'></div>
})
boxDiv.addEventListener('click', function() {
console.log(this) //<div class='box'></div>
})
boxDiv.addEventListener('click', function() {
console.log(this) //<div class='box'></div>
})
43.数组.forEach/map/filter/find 都可以接收第二个参数,进行this指向
var names = ["abc", "cba", "nba"]
names.forEach(function(item) {
console.log(this) //window
})
names.forEach(function(item) {
console.log(this)
},'abc') //abc
names.map(function(item) {
console.log(this) //cba
}, "cba")
5.箭头函数的this获取
5.1.箭头函数中this指向
箭头函数中的this,永远指向外层作用域中最接近自己的普通函数的this
箭头函数的this指向该函数定义时所在的作用域
var name = "CLF"
var foo = () => {
console.log(this);
}
foo() //window
var obj = {foo: foo}
obj.foo() //window
foo.call("abc") //window
5.2应用场景
箭头函数(因为箭头函数的this指向定义时的对象,即obj)
var obj = {
data: [],
getData: function() {
setTimeout(() => {
console.log(this)
}, 2000);
}
}
obj.getData()