用了那么久this了,还不了解它?

简介: this想必大家都很不陌生了,在例如`Vue.js`中,各种this,唰唰唰的写,但是有没有遇到this指向出错的问题呢?我有,我猜应该也会有人跟我一样。所以,我总结了一些this的基础概念和基本使用在这里,供大家参考。

前言

this想必大家都很不陌生了,在例如Vue.js中,各种this,唰唰唰的写,但是有没有遇到this指向出错的问题呢?

我有,我猜应该也会有人跟我一样。

所以,我总结了一些this的基础概念和基本使用在这里,供大家参考。

this出现在哪里

全局上下文中的this

console.log(this)来打印出来全局执行上下文中的 this,最终输出的是 window 对象。

所以可以得出这样一个结论:全局执行上下文中的 this 是指向 window 对象的。这也是 this 和作用域链的唯一交点,作用域链的最底端包含了 window 对象,全局执行上下文中的 this 也是指向 window 对象

函数上下文中的this

在全局环境中调用一个函数,函数内部的 this 指向的是全局变量 window。

通过一个对象来调用其内部的一个方法,该方法的执行上下文中的 this 指向对象本身

function foo(){
    console.log(this)
};
foo(); // window

let a = {
    b:0,
    fn:function(){
        console.log(this)
    }
}
a.fn(); //{ b:0, fn:f() }

this指向总结

  • 当函数被正常调用时,在严格模式下,this 值是 undefined,非严格模式下 this 指向的是全局对象 window;
  • 通过一个对象来调用其内部的一个方法,该方法的执行上下文中的 this 指向对象本身
  • ES6 中的箭头函数并不会创建其自身的执行上下文,所以箭头函数中的 this 取决于它的外部函数
  • new 关键字构建好了一个新对象,并且构造函数中的 this 其实就是新对象本身
  • 嵌套函数中的 this 不会继承外层函数的 this 值。

    var myObj = { 
        name : "Ned", 
        showThis: function(){ 
            console.log(this); // myObj
            var bar = function(){ 
                this.name = "阿泽"; 
                console.log(this) // window
            } 
            bar(); 
        }
    };
    myObj.showThis();
    console.log(myObj.name); // Ned
    console.log(window.name); // 阿泽
    • 解决this不继承的方法

      • 内部函数使用箭头函数
      • 将在外层函数中创建一个变量,用来存储this,内层函数通过作用域链即可访问
      var myObj = { 
          name : "Ned", 
          showThis:function(){ 
              console.log(this); // myObj
              var bar = ()=>{ 
                  this.name = "阿泽"; 
                  console.log(this) // window
              } 
              bar(); 
          }
      };
      myObj.showThis();
      console.log(myObj.name); // 阿泽
      console.log(window.name); //  
      var myObj = { 
          name : "Ned", 
          showThis:function(){ 
              console.log(this); // myObj
              var self = this;
              var bar = function (){ 
                  self.name = "阿泽"; 
                  console.log(self) // window
              } 
              bar(); 
          }
      };
      myObj.showThis();
      console.log(myObj.name); // 阿泽
      console.log(window.name); // 

改变this指向的方法

call 和 apply 的共同点

都能够改变函数执行时的上下文,将一个对象的方法交给另一个对象来执行,并且是立即执行的

调用 call 和 apply 的对象,必须是一个函数 Function

call 和 apply 的区别

call 的写法

Function.call(obj,param1,param2,...)

需要注意以下几点:

  • 调用 call 的对象,必须是个函数 Function。
  • call 的第一个参数,是一个对象。 Function 的调用者,将会指向这个对象。如果不传,则默认为全局对象 window。
  • 第二个参数开始,可以接收任意个参数。每个参数会映射到相应位置的 Function 的参数上。但是如果将所有的参数作为数组传入,它们会作为一个整体映射到 Function 对应的第一个参数上,之后参数都为空。
function func (a,b,c) {}

func.call(obj, 1,2,3)
// func 接收到的参数实际上是 1,2,3

func.call(obj, [1,2,3])
// func 接收到的参数实际上是 [1,2,3],undefined,undefined
// 其实func还是接收了三个参数,只不过咱们只传了一个过去,这个应该很容易理解的

apply 的写法

Function.apply(obj[,argArray])

需要注意的是:

  • 它的调用者必须是函数 Function,并且只接收两个参数,第一个参数的规则与 call 一致。
  • 第二个参数,必须是数组或者类数组,它们会被转换成类数组,传入 Function 中,并且会被映射到 Function 对应的参数上。这也是 call 和 apply 之间,很重要的一个区别。
func.apply(obj, [1,2,3])
// func 接收到的参数实际上是 1,2,3

func.apply(obj, {
    0: 1,
    1: 2,
    2: 3,
    length: 3
})
// func 接收到的参数实际上是 1,2,3

call 和 apply 的用途

下面会分别列举 call 和 apply 的一些使用场景。

声明:例子中没有哪个场景是必须用 call 或者必须用 apply 的,看个人习惯就好。

call 的使用场景

对象的继承如下面这个例子:

function superClass () {
    this.a = 1;
    this.print = function () {
        console.log(this.a);
    }
}

function subClass () {
    superClass.call(this);  // 执行superClass,并将superClass方法中的this指向subClass
    this.print();
}

subClass();
// 1

subClass 通过 call 方法,继承了 superClass 的 print 方法和 a 变量。

此外,subClass 还可以扩展自己的其他方法。

bind

bind 的用法

在 MDN 上的解释是:bind() 方法创建一个新的函数,在调用时设置 this 关键字为提供的值。并在调用新函数时,将给定参数列表作为原函数的参数序列的前若干项。

它的语法如下:

Function.bind(thisArg[, arg1[, arg2[, ...]]])

bind 方法 与 apply 和 call 比较类似,也能改变函数体内的 this 指向。

不同的是,bind 方法的返回值是函数,并且需要稍后调用,才会执行

而 apply 和 call 则是立即调用,来看下面这个例子:

function add (c) {
    return this.a + this.b + c;
}

var obj = {a:1,b:2}

add.bind(obj, 5); // 这时,并不会返回 8
add.bind(sub, 5)(); // 调用后,返回 8

如果 bind 的第一个参数是 null 或者 undefined,this 就指向全局对象 window。

最后

"abc"的使用,具体还是要看个人运用,理解了之后,那它们就变成了工具,怎么顺手怎么来了~

顺便说一下本人,我还是喜欢apply多一点hhh,用它的次数多一点,所以在场景用谁都行的时候,我一般都会选择apply。

点个赞,一起学习进步吧♥
相关文章
|
11月前
|
JavaScript 算法 前端开发
阿秀思考了很久,最后还是决定啦!
五月份离职后,我给自己放了半个月的假才去入职的新公司,emm,截止目前为止暂时还没后悔,如果以后真的发生北京hulu那样被一锅端的事就算我倒霉好了。
61 1
|
前端开发 程序员
写了那么久的文章,现在才改回来!
大家好,我是即兴小索奇,最近在阅读文章时发现了自己文章的一个缺陷,就记录下来并分享给大家,大家写文章时也可以借鉴。
|
程序员
能让程序员瞬间崩溃的五个瞬间,共鸣的同学请举手!
在我们的眼里,程序员好像是无所不能的,那么复杂的App和那些游戏都是他们做出来的,这让我们很难相信还有什么是他做不出来的。不过,就是我们每天眼里看着很厉害的程序员,每天都要面临的就是头疼,头疼,头好疼,特别是我接下来要说的几件事情,几乎是所有程序员都会把头抓秃的事     那么这五件事情究竟是什么事呢? 写着代码停电,代码没有保存 如果有一天突然代码写到一半,眼看就快要完工了,突然一下就断电,代码没保存。
1322 0
|
Arthas Web App开发 运维
线上 RTT 过长,我用这一招解决了!
线上 RTT 过长,我用这一招解决了!
|
监控 网络协议 Dubbo
开工第一天,这个超时问题把我干趴下了!
开工第一天,这个超时问题把我干趴下了!
|
算法 Java
一个多月的时间,终于把这件事做完了!
一个多月的时间,终于把这件事做完了!
107 0
一个多月的时间,终于把这件事做完了!
你的时间花在哪里,决定了你将成为什么样的人
你是否经常觉得时间不够用: 加班几乎成为家常便饭,工作却总是做不完;家人和朋友埋怨你陪伴他们的时间太少;想提升自己,或者去向往已久的地方度假,却总是搁置……然而,在这个世界上,还有很多比你更忙的人,他们为什么能完成远远超过常人的工作?这些人并没有拥有更多的时间,他们只是知道怎样更好地利用时间,掌控自己的时间和生活。
1432 0
《花,你何时的绚烂》(三)
《花,你何时的绚烂》(三)----张风捷特烈 你我的相遇 八月海上 不合时间 不适地点 盛夏的暴风雨 吹打着正沉沦的战船 想要拯救 那女孩澄净的眼 却只抓住了你 错过了被风吹去的再见 你依旧缄默 你是她头上花苞的簪...... 狂风吹落了花苞 用你替换了女孩的头簪 可知你的花瓣 是我对她许的诺言: “总有一天, 在你黑色的世界, 会看见, 坠落花苞的绚烂。
978 0
个人时间都干啥
我说的个人时间,是自己独处的时间,独自的时间都应该干啥,身边很多朋友不是在刷剧就是在无聊,其实不是说不可以刷剧,也不是说不可无聊,而是说,你的个人时间不应该全都是处于这种状态,或者说,你个人的大部分时间都应该处于投资自己和让自己长身价的状态 我觉得这也是一投资理财,但是唯一不同的是,这投资的是自己,而且是一个仿佛看不到收益的投资,但是这是最明智的投资,因为这个投资会随着时间的增长它的收益率大到让你想不到,可是很多人投资只喜欢短线投机,没有耐心做长线,那就很可惜了。
993 0