• JavaScript-JS中this的指向


    JavaScript-JS中this的指向

    本文将主要总结JS中this的指向

    隐式绑定的场景:

    • 全局上下文
    • 直接调用函数
    • 对象.方法的形式调用
    • DOM事件绑定(特殊)
    • new构造函数绑定
    • 箭头函数

    1. 全局上下文

    全局上下文默认this指向window, 严格模式下指向undefined。

    2. 直接调用函数

    比如:

    let obj = {
      a: function() {
        console.log(this);
      }
    }
    let func = obj.a;
    func();
    

    这种情况是直接调用。this相当于全局上下文的情况(默认this指向window, 严格模式下指向undefined。)。

    3. 对象.方法的形式调用

    还是刚刚的例子,我如果这样写:

    obj.a();
    

    这就是对象.方法的情况,this指向这个对象

    4. DOM事件绑定

    onclick和addEventerListener中 this 默认指向绑定事件的元素。

    IE比较奇异,使用attachEvent,里面的this默认指向window。

    5. new+构造函数

    此时构造函数中的this指向实例对象。

    6. 箭头函数?

    箭头函数没有this, 因此也不能绑定。里面的this会指向当前最近的非箭头函数的this,找不到就是window(严格模式是undefined)。比如:

    let obj = {
      a: function() {
        letdo = () => {
          console.log(this);
        }
        do();
      }
    }
    obj.a(); // 找到最近的非箭头函数a,a现在绑定着obj, 因此箭头函数中的this是obj
    

    显式绑定的场景:

    call, apply, bind都是为了调用函数,然后改变函数中的this的指向。
    它们允许你在调用函数时为函数指定上下文

    1.call

    • call用于显式地设置函数的上下文,call方法将对象绑定到this。
    • call 需要分别传参
    • call会立即执行函数
    function show(title) {
        alert(`${title+this.name}`);
    }
    let lisi = {
        name: '李四'
    };
    let wangwu = {
        name: '王五'
    };
    show.call(lisi, '后盾人'); //重点
    

    2.apply

    apply与call用于显式地设置函数的上下文,两个方法作用一样都是将对象绑定到this,只是在传递参数上有所不同。
    因为,我们可以看到,call方法必须一个一个传递参数,这样有些恼人。如果我们可以把整个数组作为第二个参数并让 JavaScript 为我们自动展开就好了。
    所以,这个时候apply,就派上用场了
    apply 用数组传参
    call 需要分别传参
    与 bind 不同 call/apply 会立即执行函数

    • apply用于显式地设置函数的上下文,apply方法将对象绑定到this。
    • apply 需要分别传参
    • apply会立即执行函数
    function show(title) {
        alert(`${title+this.name}`);
    }
    let lisi = {
        name: '李四'
    };
    let wangwu = {
        name: '王五'
    };
    show.apply(lisi, ['后盾人']); //重点
    

    也就是说,apply和call如果不传参数的话,只传想要改变的this的指向,那他们用法,效果都是一样的。
    func().call(self) //意思是将func()这个函数中的this指向self
    func().apply(self) //意思是将func()这个函数中的this指向self

    小栗子:
    找数组中的数值最大值

    let arr = [1, 3, 2, 8];
    console.log(Math.max(arr)); //NaN
    console.log(Math.max.call(Math, arr)); //NaN, 因为call除了要传的this以外,后面的参数必须用逗号隔开,现在传的是数组
    console.log(Math.max.apply(Math, arr)); //8, apply后的参数传的是数组
    console.log(Math.max(...arr)); //8, 当然我们用展开语法也是完全可以的
    

    3.bind

    bind()是将函数绑定到某个对象,比如 a.bind(hd) 可以理解为将a函数绑定到hd对象上即 hd.a()。
    其实,.bind.call 完全相同,除了不会立刻调用函数,而是返回一个能以后调用的新函数。

    与 call/apply 不同bind不会立即执行
    bind 是复制函数行为,会返回新函数
    bind是复制函数行为

    let a = function() {};
    let b = a;
    console.log(a === b); //true
    //bind是新复制函数
    let c = a.bind();
    console.log(a == c); //false
    

    然后呢,因为调用bind方法并不会立即执行该函数,所以就给了我们两次传参的机会;
    绑定参数注意事项

    function func(a, b) {
      return this.f + a + b;
    }
    
    //使用bind会生成新函数
    let newFunc = func.bind({ f: 1 }, 3);
    
    //1+3+2 参数2赋值给b即 a=3,b=2
    console.log(newFunc(2)); //注意如果在前面bind的时候给某些参数赋值过了,在这里就不需要赋值了,现在赋了也没用
    

    优先级: new > call、apply、bind > 对象.方法 > 直接调用。

    参考:

  • 相关阅读:
    Java框架之SpringMVC
    Java进阶之路
    Java入门基础教学(含配置环境变量等)
    Vue 入门学习
    WCF综合运用之:文件断点续传
    爬取集思录数据(1)--强赎表
    爬虫知识点(一)
    已知1、某股票的增减持日期,2、股票从上市至今的交易数据,求减持后(交易日)1天,5天,15天的收盘价。
    从tushare获取增减持数据
    生成文本序列
  • 原文地址:https://www.cnblogs.com/lskreno/p/12443381.html
Copyright © 2020-2023  润新知