速记七步口诀
箭头函数
、new
、bind
、apply和call
、obj.
、直接调用
、不在函数里
箭头函数
箭头函数排在第一个是因为它的 this 不会被改变,所以只要当前函数是箭头函数,那么就不用再看其他规则了
箭头函数的this
是在创建它时外层this
的指向
- 创建箭头函数时,就已经确定了它的
this
指向 - 箭头函数内的
this
指向外层的this
所以要知道箭头函数的this
就得先知道外层this
的指向,需要继续在外层应用七步口诀
new
当使用new
关键字调用函数时,函数中的this
一定是 JS 创建的新对象
注意
箭头函数不能作为构造函数,也就不能和new
一起使用
bind
bind
是指Function.prototype.bind()
- 多次
bind
时只认第一次bind
的值
js
function func() {
console.log(this)
}
func.bind(1).bind(2)() // 1
- 箭头函数中
this
不会被修改
js
func = () => {
// 这里的 this 指向取决于外层 this,参考口诀 7 「不在函数里」
console.log(this)
}
func.bind(1)() // Window
bind
与new
js
function func() {
console.log(this, this.__proto__ === func.prototype)
}
bindFunc = func.bind(1)
new bindFunc() // Object true, 口诀 2 「new」优先
apply
和call
apply()
和call()
的第一个参数都是this
,区别在于通过apply
调用时实参是放到数组中的,而通过call
调用时实参是逗号分隔的
- 箭头函数中
this
不会被修改
js
func = () => {
// 这里的 this 指向取决于外层 this,参考口诀 7 「不在函数里」
console.log(this)
}
func.apply(1) // Window
bind
函数中this
不会被修改
js
function func() {
console.log(this)
}
bindFunc = func.bind(1)
bindFunc.apply(2) // 1, 口诀 3 「bind」优先
obj.
js
function func() {
console.log(this.x)
}
obj = { x: 1 }
obj.func = func
obj.func() // 1
直接调用
在函数不满足前面的场景,被直接调用时,this
将指向全局对象。在浏览器环境中全局对象是Window
,在 Node.js 环境中是Global
js
function outerFunc() {
console.log(this) // { x: 1 }
function func() {
console.log(this) // Window
}
func()
}
outerFunc.bind({ x: 1 })()
不在函数里
不在函数中的场景,可分为浏览器的<script />
标签里,或 Node.js 的模块文件里
- 在
<script />
标签里,this
指向Window
- 在 Node.js 的模块文件里,
this
指向Module
的默认导出对象,也就是module.exports
非严格模式
严格模式是在 ES5 提出的。在 ES5 规范之前,也就是非严格模式下,this
不能是undefined
或null
所以在非严格模式下,通过上面七步口诀,如果得出this
指向是undefined
或null
,那么this
会指向全局对象。在浏览器环境中全局对象是Window
,在 Node.js 环境中是Global
js
function func() {
console.log('function func:', this)
;(() => {
console.log('arrow function: ', this)
})()
}
func()
func.bind(null)()
func.bind(undefined)()
func.bind().bind(2)()
func.apply()
注意
七步口诀在严格模式下和非严格模式下都是完备的,只是在非严格模式下null
或undefined
会被转换为全局对象,所以没有将这点列入口诀中