小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
前言
大家都知道函数的this是动态的, 未到执行之时,不知道他是谁。 刺激不刺激,今天我们就一起来了解函数的this。
动态的this
浏览器下执行下面的代码:
var name = "window"
function logName(){
console.log(this.name, this)
}
function logName2(){
"use strict"
console.log("this:", this)
}
var person = {
name: "person",
logName
}
logName();
// window Window {window: Window, self: Window, document: document, name: 'window', location: Location, …}
logName2()
// this: undefined
person.logName();
// person {name: 'person', logName: ƒ}
可以看出, logName直接执行和作为一个属性执行,this的输出是完全不一样的。
顺便,我们通过logName2也验证了,严格模式下, this为undefined。
改变this的方式
一起看看常见的改变函数this的方法方式。
call
function logName(){
console.log(this.name, this)
}
logName.call({name: "haha"})
// haha {name: 'haha'}
apply
function logName(){
console.log(this.name, this)
}
logName.apply({name: "haha"})
// haha {name: 'haha'}
bind
bind额外说一下,返回的是一个函数。
function logName(){
console.log(this.name, this)
}
logName.bind({name: "haha"})()
// // haha {name: 'haha'}
new
function logName(){
console.log(this.name, this)
}
logName.prototype.name = "哎哟";
new logName();
// 哎哟 logName {}
函数作为构造函数的时候, this 是logName的实例。
作为属性
这是函数的一个基本特征,也是改变this的一种方式吧。
function logName(){
console.log(this.name, this)
}
var person = {
name: "person",
logName
}
// person {name: 'person', logName: ƒ}
锁定this的方式
有改变就有锁定, this, 你往哪里跑!
bind
function logName(){
console.log(this.name, this)
}
var person = {
name: "person",
}
logName.bind(person).call({name: "o"})
// person {name: 'person'}
可以看到,用bind绑定this之后,再想用 call去改变this,是不行的。
logName.bind(person).bind({name: "o"})
// person {name: 'person'}
同样的,多次bind,第一次生效!
箭头函数
var name = "window";
var person = {
name: "person",
logName: () => {
console.log(this.name, this)
}
}
person.logName();
// window Window {window: Window, self: Window, document: document, name: 'window', location: Location, …}
可以看到结果是name属性的值是window,因为箭头函数把this绑定到当时所处的上下文。
:: 函数绑定符
函数绑定符。
({name:"123"})::logName()
// 等同于 logName.bind({name:"123"})
// 123
更多信息可以参见 proposal-bind-operator
小结
- 动态的this
执行的时候,才确定 - 有好几种方式可以改变this
call, apply, bind和new都可以 - 也有好几种方式绑定this
bind,箭头函数,::绑定符
今天你收获了吗?