这个this的解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 首先得理解this是在函数被调用的时候绑定的,完全取决于函数的调用位置。这与静态作用域相反,反而有点类似动态作用域(由运行时决定)。this在运行时才进行对象绑定。其次,就是我们常见的this指向问题,即this的绑定。

网络异常,图片无法展示
|

this 的理解


首先得理解this是在函数被调用的时候绑定的,完全取决于函数的调用位置。这与静态作用域相反,反而有点类似动态作用域(由运行时决定)。this在运行时才进行对象绑定。

其次,就是我们常见的this指向问题,即this的绑定。


this的绑定规则


默认绑定


大家可能会好奇默认绑定是什么?它就是非严格模式下,函数在全局环境中运行,函数内部的this指向的是window对象。


var a = '我是全局环境下的a';
function fun() {
  console.log(this);
  console.log(this.a);
}
fun()
// Window对象
// 我是全局环境下的a


从fun函数中输出的this就可以看出,全局下的独立函数运行,内部的this绑定的是window对象。


网络异常,图片无法展示
|
严格模式下,函数内部调用this为 undefined,函数内部调用全局变量a直接报错!


隐式绑定


隐式绑定需要考虑有无上下文对象的情况。当函数引用有上下文对象时,隐式绑定就会把this绑定到这个上下文对象中。

var a = 0
function fun() {
  console.log(this.a);
}
let obj = {
  a: 1,
  fun: fun,
}
obj.fun() // 1


函数fun在全局声明,它作为引用属性被添加到obj中。 严格来说,不管fun函数在全局声明还是在objfun中声明,fun这个函数都不属于obj对象。


主要是看函数被调用时的上下文对象。

上例中:函数在obj内调用,即obj.fun()。此时fun()的上下文对象为obj,this指向字面量obj。所以输出的是obj内部的a变量。


var a = 0
function fun() {
  console.log(this.a);
}
let obj = {
  a: 1,
  fun: fun,
}
let o = obj.fun
o() // 0


此例,将obj.fun用一个全局变量保存,之后再运行该全局变量。运行时,上下文对象为全局的window。所以fun函数中的this,指向window,输出全局的a变量0。当然此例需要在非严格模式下运行,否则this绑定的对象丢失,则为undefined。


显式绑定


如果想要强制地在某个对象中调用函数,将this绑定到这个对象中。我们可以使用call()apply(),传入想要绑定的this的对象。直接指定this所指对象。


let a = 'window 中的 a'
function fun() {
  console.log(this.a);
}
let obj = {
  a: 'obj 中的 a '
}
fun.call(obj) // obj 中的 a 
fun.apply(obj) // obj 中的 a 


两者第一个参数都是this所指的对象。call()apply()的区别在于传入的参数不同,call()方法分别接受参数,而apply()方法接受数组形式的参数。后续会详细讲解call()apply()的实现。


new绑定


构造函数:指使用new操作符时被调用的普通函数。它不属于某个类,也不会实例化一个类。 需要特别注意的是,不存在所谓的构造函数,只有对于函数的构造调用

js中new的运行机制(new的过程):


1、构造一个全新的对象

2、这个新对象会被执行[[prototype]]连接(包含原型、原型链)

3、绑定到函数调用的this

4、如果函数没有其他返回对象,那么new表达式中的函数调用会自动返回这个新对象。

在此,我们主要讨论的是this。


function Fun(a) {
  this.a = a
}
var obj = new Fun(2)
console.log(obj.a);  // 2


使用new绑定,obj调用Fun(),此时this指向obj。所以在obj变量中包含了a属性。obj.a输出为2。


绑定优先级


毫无疑问,默认绑定的优先级肯定是最低的。


隐式绑定和显式绑定比较


let a = 'window 中的 a'
function fun() {
  console.log(this.a);
}
let obj = {
  a: 'obj 中的 a ',
  fun: fun
}
let test = {
  a: 'test 中的 a'
}
obj.fun() // obj 中的 a 
obj.fun.call(test) // test 中的 a


call改变了obj中fun函数中的this,将this.a指向了test中的a属性。所以显式绑定的优先级高于隐式绑定。


隐式绑定和new绑定比较


function fun(a) {
  this.a = a
  console.log(this.a);
}
let obj = {
  a: 'obj 中的 a ',
  fun: fun
}
obj.fun(obj.a) // obj 中的 a 
let o = new obj.fun('o 中的 a') // o 中的 a


new obj.fun('o 中的 a')中,new将原本this绑定的obj,转移到了o变量上。并给o内部的a属性赋值,即o 中的 a


显示绑定和new绑定比较


无法通过new fun.call(obj)直接进行测试,但是可以通过bind绑定来测试。

function fun(a) {
  this.a = a
  console.log(this);
}
var obj = {}
var bar = fun.bind(obj)
bar(2)
console.log(obj.a);
var baz = new bar(3)
console.log(baz.a);
// 结果
// {a: 2}
// 2
// fun {a: 3}
// 3
复制代码


使用bind绑定后,this指向了obj,可以看到输出的this为{a: 2}。当new时,修改了bind绑定,将this指向了baz。因此我们得到了baz这个新对象。


总结:


new绑定 > 显式绑定 > 隐式绑定 > 默认绑定


箭头函数


箭头函数不会根据上面this的绑定规则,而是根据词法作用域(静态作用域)决定this的。箭头函数会继承外层函数调用的this绑定。与使用一个变量保存this机制一样。

function fun() {
  setTimeout(() => {
    console.log(this);
  }, 0)
  setTimeout(function () {
    console.log(this);
  }, 0)
}
let obj = {
  a: "obj 中的 a",
  fun: fun
}
obj.fun()
// {a: "obj 中的 a", fun: ƒ}
// Window
复制代码


从上例中可以看出,使用箭头函数的第一个setTimeout中this指向的是obj。也可以将箭头函数理解成函数表达式,直接使用fun所指的this。


参考书籍:《你不知道的JavaScript》上券

目录
相关文章
|
自然语言处理 JavaScript 前端开发
深度解析javascript中的this(四)
深度解析javascript中的this(四)
97 0
|
JavaScript 前端开发
深度解析javascript中的this(三)
深度解析javascript中的this(三)
88 0
|
JavaScript 前端开发 API
深度解析javascript中的this(二)
深度解析javascript中的this(二)
83 0
|
自然语言处理 JavaScript 前端开发
深度解析javascript中的this(一)
深度解析javascript中的this(一)
94 0
|
JavaScript 前端开发 API
你不知道的js中关于this绑定机制的解析[看完还不懂算我输]
前言 最近正在看《你不知道的JavaScript》,里面关于this绑定机制的部分讲的特别好,很清晰,这部分对我们js的使用也是相当关键的,并且这也是一个面试的高频考点,所以整理一篇文章分享一下这部分的内容,相信看本文的解析,你一定会有所收获的,如果喜欢的话可以点波赞/关注,支持一下。 游泳、健身了解一下:博客、前端积累文档、公众号、GitHub 为什么要用this: function identify() { console.log("Hello,I'm " + this.name); } let me = { name: "Kyle" }; let you = { nam
119 0
你不知道的js中关于this绑定机制的解析[看完还不懂算我输]
|
JavaScript 前端开发 开发者
JavaScript之this解析
this的关键字是JavaScript中最复杂的机制之一,它是一个很特别的关键字,被自动定义在所有函数作用域中。但是即使是非常有经验的JavaScript开发者也很难说清它到底指向的是什么。 ——来源《你不知道的JavaScript上卷》
533 1
JavaScript之this解析
|
JavaScript 前端开发
牛客最新前端笔试题解析(一) this指向题目解析及扩展
牛客最新前端笔试题解析(一) this指向题目解析及扩展
311 0
|
JavaScript
你不知道的js中关于this绑定机制的解析[看完还不懂算我输]
最近正在看《你不知道的JavaScript》,里面关于this绑定机制的部分讲的特别好,很清晰,这部分对我们js的使用也是相当关键的,并且这也是一个面试的高频考点,所以整理一篇文章分享一下这部分的内容,相信看本文的解析,你一定会有所收获的,如果喜欢的话可以点波赞/关注,支持一下。
1216 0

推荐镜像

更多