为什么说搞清楚this的指向对项目开发很重要?

129 阅读2分钟

前言

在项目中,this的变化让人晕头转向,但是它其实并不难,今天我们函数中this的指向,和this绑定的场景,以及绑定
this的优先级,来聊聊this的指向。

this的指向

全局函数的this指向

var a = 10
var a =function () {
    console.log(this)//window
}
a()

对象方法的this指向

//对象方法里的this指当前对象
var obj = {
    name: '张三',
    say() {
        console.log(this.name);
    }
}
obj.say()//张三

事件函数里的this指向

//事件函数里的this指向触发对象
document.querySelector('button').onclick = function () {
    console.log(this.name);//button
}

​ 没有归属的匿名函数this指向

//没有归属的匿名函数this指向window
var a = 2
function fun() {
    console.log(this.a);
}
var o = {
    a: 3,
    fun: fun
}
o.fun()//3
var p = {
    a: 4
}
console.log(p.fun = o.fun);
;(p.fun = o.fun)();//2

​ 箭头函数的this指向

//箭头函数没有自己的this,会使用外层作用域的this
console.log(this)//window
var a = 2
var test = () => {
    console.log(this.a)//2
}
test()
var obj = {
    a: 3,
    show() {
        var test = () => {
            console.log(this.a);//3
        }
        test()
    }
}
obj.show()

​ 对象中方法的函数this指向

//对象方法中的函数this指向window
var a = 2
var obj = {
    a: 3,
    show() {
        var test = function () {
            console.log(this.a);//2
        }
        test()
    }
}
obj.show()

显示绑定this

Function.prototype.call()

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
function foo(str1,str2){
    console.log(this,str1,str2) //"aaa" 'str1' 'str2'
}
foo.call('aaa','str1','str2')

Function.prototype.apply()

apply() 方法调用一个具有给定 this 值的函数,以及以一个数组(或一个类数组对象)的形式提供的参数。
function foo(str1,str2){
    console.log(this,str1,str2) //"bbb" 'str1' 'str2'
}
foo.apply('bbb',['str1','str2'])

Function.prototype.bind()

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将
作为新函数的参数,供调用时使用。
function foo(str1,str2){
    console.log(this,str1,str2) //'ccc','str1','str2'
}
let bar = foo.bind('ccc','str1','str2')
bar()

new的this指向

this指向实例对象
function MyClass(){
    
}
let myClass = new MyClass()
console.log('myClass',myClass)

绑定this的优先级(绑定this对象使用多种方式绑定)

new和默认this绑定

myClass.foo()//实例对象
结论 new的优先级高于隐式this绑定

new和call,apply

newcall、apply不能同时使用

new和bind

function foo(){
    console.log(this)
}
let bar = foo.bind({name:'bar'})
let obj = {
    bar
}
console.log(new obj.bar()) //空对象

bind和call和apply

bind的优先级高于call和apply
function foo(){
    console.log(this)
}
let bar = foo.bind({name:'bar'})
console.log(bar.call('call'))//{name:'bar}
console.log(bar.call('apply'))//{name:'bar}

结论 new的优先级>bind的优先级>call和apply的优先级>隐式绑定的优先级>默认绑定的优先级