资讯专栏INFORMATION COLUMN

小菊花课堂之JavaScript关于this

CHENGKANG / 3100人阅读

摘要:另外,的绑定和函数声明的位置没有任何关系,之取决于函数的调用方式。请看下面代码这样,我们就可以在调用的时候强制把它的绑定到上绑定在传统的面向类语言中,使用初始化类时会调用类中的构造函数。

关于this

上一章我们讲了关于作用域和闭包的相关知识,现在开始新一轮的学习,那就是JavaScript中最复杂的机制之一---this关键字。它是一个很特别的关键字,被自动定义在所有函数的作用域中。另外我们需要明确的一点就是,this在任何情况下都不指向函数的词法作用域。

那么我们来看看this到底是怎么样的机制。this是在运行时进行绑定的,它的上下文取决于函数调用时的各种条件。另外,this的绑定和函数声明的位置没有任何关系,之取决于函数的调用方式。

this的四条绑定规则 默认绑定

默认绑定就是最常用的独立函数调用时所绑定的。思考一下代码

function foo() {
    console.log(this.a);
}
var a = 2;
foo(); // 2

我们可以看到,当调用foo()时,this.a被解析成了全局变量a。
但是,如果使用严格模式,那么就不能将全局对象用于默认绑定,报错TypeError:this is undefined

隐式绑定

一个对那个内部包含一个指向函数的属性,并通过这个属性间接引用函数,从而把this隐式绑定到这个对象上。所以这一条就需要考虑调用位置是否有上下文对象。

function foo() {
    console.log(this.a);
}
var obj = {
    a : 2,
    foo: foo
};
obj.foo(); // 2

这段代码中,当foo()被调用时,前面加上了对obj的引用。当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象。另外,对象属性引用链中只有上一层或者说最后一层在调用位置中起作用。也就是说,this永远都是指向最近调用的位置。

显式绑定

前面说了隐式绑定的概念,那么我们如果不想在对象内部包含函数引用,而想在某个对象上强制调用函数,该如何做呢?
JavaScript中提供了两个方法,分别是call()apply(),那么我们应该怎么在实际中运用呢?
首先我们要搞清楚call()apply()的作用,这里引用MDN上的解释:

call() 方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表)。
apply() 方法调用一个具有给定this值的函数,以及作为一个数组(或类似数组对象)提供的参数。
具体如何实现,这里不作展开说明,可以自行研究,加深理解。

可以看出,它们俩的差异仅在于所需参数的形式不同,ok回归正题。
请看下面代码:

function foo() {
    console.log(a);
}
var obj = {
    a: 2
}
foo.call(obj); // 2

这样,我们就可以在调用foo的时候强制把它的this绑定到obj上

new绑定

在传统的面向类语言中,使用new初始化类时会调用类中的构造函数。但是,JavaScript中的构造函数只是使用new操作符时被调用的函数。它们并不属于某个类,也不会实例化一个类。
JavaScript中使用new调用函数时,会自动执行下面操作

构造一个新对象

新对象会被执行[[prototype]]连接

新对象会绑定函数调用的this

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

判断this

那么我们在判断函数在某个调用位置应该应用哪条规则呢,优先级如何判断呢?有下面四条法宝供参考

函数是否在new中调用?如果是,则this绑定的是新对象
var bar = new foo()

函数是否通过call、apply调用?如果是,则this绑定的是指定对象
var bar = foo.call(obj)

函数是否在某个上下文对象中调用?如果是,则this绑定的是上下文对象
var bar = obj.foo()

如果都不是的话,使用默认绑定。注意,在严格模式下,就绑定到undefined,否则就绑定到全局对象
var bar = foo()

当然,也许会有例外的情况发生,暂时先留着,大家一起思考一下,看看会在什么情况下出现这种例外情况。

那么,今天就先到这里啦
see u ~ again

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99220.html

相关文章

  • 菊花课堂JavaScript作用域与闭包

    摘要:而闭包却能阻止这件事情发生。由于的声明位置使它拥有涵盖内部作用域的闭包,使得该作用域能够一直存在,以供在之后进行引用。到这里,小菊花课堂之闭包的内容就告一段落啦,感谢各位能耐心看到这里。 由于前段时间项目没有那么忙,然后我这人一天不看点啥就非常焦虑,于是二刷《你不知道的JavaScript》,现在读到闭包,想着看完这一章节,写点东西也是挺好的,所以有了下面的内容,如有不对的地方,敬请斧...

    lunaticf 评论0 收藏0
  • 菊花课堂JS的防抖与节流

    摘要:文章来源详谈防抖和节流轻松理解函数节流和函数防抖函数防抖和节流好啦,今天的小菊花课堂之的防抖与节流的内容就告一段落啦,感各位能耐心看到这里。 前言 陆游有一首《冬夜读书示子聿》——古人学问无遗力,少壮工夫老始成。纸上得来终觉浅,绝知此事要躬行。,其中的意思想必大家都能明白,在学习或工作中,不断的印证着这首诗的内涵。所以,又有了此篇小菊花文章。 详解 在前端开发中,我们经常会碰到一些会持...

    leoperfect 评论0 收藏0
  • 菊花课堂JS的防抖与节流

    摘要:文章来源详谈防抖和节流轻松理解函数节流和函数防抖函数防抖和节流好啦,今天的小菊花课堂之的防抖与节流的内容就告一段落啦,感各位能耐心看到这里。 前言 陆游有一首《冬夜读书示子聿》——古人学问无遗力,少壮工夫老始成。纸上得来终觉浅,绝知此事要躬行。,其中的意思想必大家都能明白,在学习或工作中,不断的印证着这首诗的内涵。所以,又有了此篇小菊花文章。 详解 在前端开发中,我们经常会碰到一些会持...

    Yangder 评论0 收藏0
  • 干货--手把手撸vue移动UI框架: 滑动加载

    摘要:前言在我们移动端还有一个很常用的组件,那就是滑动加载更多组件。平常我们看到的很多插件实现相当复杂就觉得这个组件很难,其实不是的这个组件其实可以很简单的就实现出来,而且体验也能非常的棒当然我们没有实现下拉刷新功能下面我们就一起来实现这个组件。 前言 在我们移动端还有一个很常用的组件,那就是滑动加载更多组件。平常我们看到的很多插件实现相当复杂就觉得这个组件很难,其实不是的!!这个组件其实可...

    Harpsichord1207 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<