JavaScript中 this 指向问题

1,718 阅读3分钟

前言

本文整理了js的this的五种绑定规则以及常见js指向问题,如果对答案有不一样见解的同学欢迎评论区补充讨论,当然有问题,也欢迎在评论区指出。

一、理解this

this是什么?首先this不是指向自身!this 是一个指针,指向调用函数的对象。其次需要知道this的五种绑定规则

二、this五种绑定规则

优先级:5>4 > 3(bind>apply/call)> 2 > 1

1、默认绑定规则:直接调用,this 指向 window。

2、隐式绑定规则:谁调用就指向谁。this 永远指向最后调用它的那个对象

3、显式绑定规则:this 指向 call、apply、bind 函数的第一个传参。

4、new 绑定规则:this 指向构造函数产生的对象。

5、箭头函数

三、this的指向问题

1、箭头函数

  • this 不会被改变
  • 创建箭头函数时,箭头函数内的 this 指向外层的 this。

2、new

当使用 new 关键字调用函数时,函数中的 this 一定是 JS 创建的新对象。

function func(){
    console.log(this);
}
new func() // this指向func {}

3、bind

bind 是指 Function.prototype.bind()。

bind() 函数会创建一个新的绑定函数,需要加一个()调用,调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。多次调用bind(),以第一个bind为主

function func() {
    console.log(this); // 1
}
func.bind(1,2,3).bind(2)()

绑定函数也可以使用new运算符构造,(bind和new)

function func() {
    console.log(this) //func {}
}
fun = func.bind(1);
new fun() //优先级高

4、apply和call

apply() 和 call()的this都被指定为第一个参数,且都是直接调用,而bind是创建一个新函数,区别是

  • apply的其余参数放到数组中。

  • call的其余参数是用逗号分隔的。

    function func(args) {
        console.log(this,args) //[Number: 1]  2
    }
    func.apply(1,[2,3]);
    func.call(1,2,3)
    

5、隐式绑定操作,谁调用就指向谁

function func() {
    console.log(this)  //{ name: 'hzy', func: [Function: func] } --- 指向obj
}
obj = {name:'hzy'} //赋值操作
obj.func = func;
obj.func()
​
var name = "windowsName";
var a = {
    name: "Cherry",
    fn : function () {
        console.log(this.name);      // Cherry
    }
}
window.a.fn();  //最后调用的是a,所以指向avar name = "windowsName";
var a = {
    name : null,
    // name: "Cherry",
    fn : function () {
        console.log(this.name);      // windowsName
    }
}
​
var f = a.fn;   //虽然将 a 对象的 fn 方法赋值给变量 f 了,但是没有调用
// 如果这样的话:var f=a.fn()  --- 会打印null
f();  //最后调用的是fn,所以指向window,打印windowName

6、直接调用

在函数不满足前面的场景,被直接调用时,this 将指向全局对象。在浏览器环境中全局对象是 Window,在 Node.js 环境中是 Global。

function func() {
    console.log(this) // window/global
}
func()
​
function outerFunc() {
    console.log(this) // { x: 1 }
    function func() {
        console.log(this) // Window
    }
    func()
}
outerFunc.bind({ x: 1 })()

7、不在函数里

不在函数中的场景,可分为浏览器的 < scrip >标签里,或 Node.js 的模块文件里。this指向window或global

8、Prototype

Array.prototype._map = function (callback) {
    if(typeof callback !== 'function') {
        throw new Error('callback is not function')
    }
    console.log(this)    //this--------------------------->  实例对象  [1,5,6]
    return this.reduce((prev,item,index,arr) => {
        prev.push(callback(item, index, arr))
        return prev
    }, [])
}
​
let val = [1, 5, 6]._map(item => item+ 1)

总结

觉得写得好的,对你有帮助的,可以分享给身边人,知识越分享越多,千万不要吝啬呀

后续更新前端其它小知识总结,请关注我,整理好,分享给你们,我们一起学前端