参考:https://mp.weixin.qq.com/s/b_SojysoGA_Z7WLJrilizg
一、原理
js函数中的this变量指向是什么?这和this所在的函数的声明和调用情况有关
1. 函数作为对象的属性被调用
作为哪个对象的函数调用的,函数中的this就指向哪个对象。如果在全局环境中调用,this指向window(strict模式时候是undefined)
2. 通过call、apply调用
call和apply都是Function.prototype上的方法。
call和apply可以改变this指向。
当函数调用call()和apply()时,函数都会立即执行。 call和apply的第一个参数都是要绑定的对象。call方法可以传给该函数的参数分别作为自己的多个参数,而apply方法必须将传给该函数的参数合并成一个数组作为自己的一个参数:
const person = {name: 'Sam'};
function log(a, b) {
console.log(this.name, a, b);
}
log.call(person, 1, 2); // Sam 1 2
log.apply(person, [1, 2]); // Sam 1 2
3. bind绑定后的函数
bind可以将函数的this绑定到指定对象,优先级高于call、apply。
bind后返回一个新的函数。
bind时候还可以传入固定参数。
const person = {name: 'Sam'};
function log(a, b) {
console.log(this.name, a, b);
}
const log1 = log.bind(person, 1, 2);
log1(); // Sam 1 2
4. 使用new调用(当做构造函数调用)
如果函数被当做构造函数调用,函数中的this指向的是实例。优先级高于bind
5. 箭头函数
箭头函数中的this指向的是它声明时候所在的函数的this。如果在全局声明,那this指向window。
箭头函数的优先级最高,使用call或者apply不会改变指向,使用bind的话,也不会改变this指向,但是bind指定的参数会传给函数。
二、题目
function showThis () {
console.log(this)
}
function showStrictThis () {
'use strict'
console.log(this)
}
showThis() // window
showStrictThis() // undefined
var boss = {
name: 'boss',
returnThis () {
return this
}
}
boss.returnThis() === boss // true
var boss1 = {
name: 'boss1',
returnThis () {
return this
}
}
var boss2 = {
name: 'boss2',
returnThis () {
return boss1.returnThis()
}
}
var boss3 = {
name: 'boss3',
returnThis () {
var returnThis = boss1.returnThis
return returnThis()
}
}
boss1.returnThis() // boss1
boss2.returnThis() // boss1
boss3.returnThis() // window
var boss1 = {
name: 'boss1',
returnThis () {
return this
}
}
var boss2 = {
name: 'boss2',
returnThis: boss1.returnThis
}
boss2.returnThis() //boss2
function returnThis () {
return this
}
var boss1 = { name: 'boss1' }
returnThis() // window
returnThis.call(boss1) // boss1
returnThis.apply(boss1) // boss1
function returnThis () {
return this
}
var boss1 = { name: 'boss1'}
var boss1returnThis = returnThis.bind(boss1)
boss1returnThis() // boss1
var boss2 = { name: 'boss2' }
boss1returnThis.call(boss2) // still boss1
function showThis () {
console.log(this)
}
showThis() // window
new showThis() // showThis
var boss1 = { name: 'boss1' }
showThis.call(boss1) // boss1
new showThis.call(boss1) // TypeError call is not a constructor call不能被用作构造函数
var boss1showThis = showThis.bind(boss1)
boss1showThis() // boss1
new boss1showThis() // showThis
function callback (cb) {
cb()
}
callback(() => { console.log(this) }) // window
var boss1 = {
name: 'boss1',
callback: callback,
callback2 () {
callback(() => { console.log(this) })
}
}
boss1.callback(() => { console.log(this) }) // still window
boss1.callback2() // boss1
var returnThis = () => this
returnThis() // window
new returnThis() // TypeError
var boss1 = {
name: 'boss1',
returnThis () {
var func = () => this
return func()
}
}
returnThis.call(boss1) // still window
var boss1returnThis = returnThis.bind(boss1)
boss1returnThis() // still window
boss1.returnThis() // boss1
var boss2 = {
name: 'boss2',
returnThis: boss1.returnThis
}
boss2.returnThis() // boss2