手机版

JavaScript函数中的四种绑定形式

时间:2021-09-03 来源:互联网 编辑:宝哥软件园 浏览:

主体

这在javascript中与函数密切相关,所以今天,我将详细告诉大家:这在javascript函数中

说到这,很多晕乎乎的抽象概念就出来了。这里我只说,——函数中这个的核心点总是指向调用它的对象,下面的故事将集中讨论这一点

(提醒前排的奶酪准备茶和西瓜,我要开始讲故事了!)

【故事】有个年轻人叫‘这个’。有一天,Diss意外穿越了一个叫“javascript”的不同世界。这一刻,迪斯身无分文。他要做的第一件事就是在——中找到他的住宿地点,并在——中调用函数对象。

此的默认绑定

【故事——第一行】如果这位直到天黑都找不到地方收留自己,他将作为非洲难民生活。这时,一位仁德的巫师村长——window救世主一般出现了:先呆在我家!

[文本]

当函数没有显式调用对象时,也就是说,它只是作为一个独立的函数被调用,默认绑定将用于该函数:绑定到全局窗口对象

function fire(){ console . log(this===window)} fire();//输出为真。我相信上面的例子对大多数人来说都很简单,但是有时候我们在改变例子的时候会很困惑:

Function fire () {//我是函数内部定义的函数!函数innerFire(){ console . log(this===window)} innerFire();//独立函数调用} fire();//输出真函数innerFire是在外部函数Fire中声明和调用的,那么它的这个指向是谁呢?依然是一扇窗

很多人可能会关心fire函数的作用域对innerFire的影响,但是我们只需要在我们的理论武器——没有明确的调用对象:绑定到全局窗口对象时,使用这个函数的默认绑定,就可以得到正确的答案

下面的增强示例也是同样的输出

var obj={ fire : function(){ function innerFire(){ console . log(this===window)} innerFire();//独立函数调用} } obj . fire();//输出true[注意]在这个例子中,obj.fire()的调用实际上使用了这个的隐式绑定,这也是我接下来要讲的,接下来我会继续解释这个例子。

【总结】所有函数都作为独立函数调用。无论它们位于何处,它们的行为与在全球环境中直接呼叫没有什么不同

这个的隐式绑定

【故事——第二行】当这个穿越世界的“javascript”时,他只是带了一些钱,所以他找了一家酒店住下。

当一个函数被一个对象“包含”时,我们说这个函数隐式地绑定到这个对象。此时,绑定对象中的其他属性可以通过这个直接访问,比如下面的A属性

var obj={ a: 1,fire : function(){ console . log(this . a)} } obj . fire();//输出1现在我们需要深入思考常见的代码操作。首先,以下两个代码达到了相同的效果:

//我是第一个代码函数fire(){ console . log(this . a)} varobj={ a :1,fire 3360 fire } obj . fire();//输出1//我是第二个代码varobj={a: 1,fire 3360 function(){ console . log(this。a)} } obj . fire();//output 1fire函数没有什么不同,因为它是在obj对象内部和外部定义的,也就是说,在上面两种形式的隐式绑定中,fire仍然可以通过这个来访问obj中的a属性,这告诉我们:

1.这是动态绑定的,或者在代码运行时绑定,而不是在编写时绑定

2.功能与对象的独立性,以及这种独立性的传递损失

(下面的描述可能不太严谨,带有个人情感倾向,但这是因为我希望读者能尽可能理解我想表达的内容。)在隐式绑定下,作为对象属性的函数,它独立于对象。

基于这种动态绑定的特性,它作为对象属性的函数被写入对象内部,这对于该对象是独立的。(该函数不“完全由”该外部对象拥有)

我想说的是:在上面,虽然函数是在对象内部定义的,但是“在对象外部声明函数,然后借助对象内部的属性名获取函数的引用”在本质上是等价的(不仅仅是在效果上)

对象内部定义的函数只是“刚好可以被这个对象调用”,而不是“天生为这个对象被调用”

用下面这个隐式绑定中的转移损失问题来说明:

Var obj={a: 1,//a是属性1fire 3360 function () {console。日志(这个。a)} } var a=2;//a是在全局环境中定义的变量:2var fireInGrobal=obj.fireFireIngrobal();//输出2上面简单代码的有趣之处在于,当调用obj中fire函数的引用(fireInGrobal)时,行为表达式(Output)根本看不到,而且是在obj内部定义的,原因是我们失去了这个隐式绑定!因此,当fireInGrobal调用的不是obj,而是window时获得的

上述示例中的一个微小变化将成为困扰我们的bug:

在那里,我们的

var a=2;Var obj={a: 1,//a是属性fire 3360 function(){ console . log(this。a)}}函数other fire(fn){ fn();} other fire(obj . fire);output2的关键作用是otherFire函数,它接受一个函数引用作为参数,然后直接在内部调用。然而,它假设参数fn仍然可以通过这个获得obj内部的a属性,但事实上,这个到obj的绑定已经丢失,所以它输出的是a (2)的全局值,而不是内部obj (1)的值

在一串对象属性链中,它被绑定到最里面的对象

在隐式绑定中,如果函数调用位置在一串对象属性链中,这将绑定最里面的对象。如下图所示:

var obj={ a: 1,obj2: { a: 2,obj3: { a:3,GetA : function(){ console . log(this . a)} } } obj . obj 2 . obj 3 . GetA();//输出3的显式绑定:(调用和绑定方法)

【故事——第3行】这个穿越世界的“javascript”,经过努力积累了一定的财富,于是买了自己的房子

上面,我们提到了这个绑定在这个的隐式绑定中丢失的问题,也就是说,对于“fireInGrobal=obj.fire”

fireInGrobal调用和obj.fire调用的结果是不同的,因为这个函数的赋值过程无法通过这个fire绑定。这时,调用函数就派上了用场

call的基本用法:fn.call(object)

Fn是您调用的函数,而object参数是您希望函数的这个绑定到的对象。

fn.call(对象)的功能:

1.立即调用该函数(fn)

2.当调用这个函数时,这个函数指向对象对象

示例:

Var obj={a: 1,//a是属性fire3360function () {console。日志(这个。a)} } var a=2;//a是全局环境中定义的变量varfireningglobal=obj.fireFireIngrobal();//输出2fireningglobal。呼叫(obj);//输出1。fireInGrobal丢失了绑定到obj的这个参数,再次将这个参数绑定回obj。

然而,我们并不真的喜欢每次通话都依赖通话的方式。我们希望可以一次返回一个带有这个永久绑定到obj的fireingobal函数,这样我们就不必每次调用fireingobal时都在尾部添加call。

我该怎么办?如果你很聪明,你可以认为在fireingobal之外包装一个函数是不够的。呼叫!

Var obj={a: 1,//a是属性fire3360function () {console。日志(这个。a)} } var a=2;//a是全局环境中定义的变量var fn=obj.firevar fireingbal=function(){ fn。call(obj)//硬绑定} fireingbal();//如果使用bind,输出1会更简单

var firening global=function(){ fn。call(obj)//硬绑定}可以简化为:

var FireIngrobal=fn . bind(obj);调用和绑定的区别在于,当将它绑定到对象参数时:

1.call将立即执行该函数

2.bind不执行函数,只返回一个可以执行的函数

【其他】:至于申请,除了使用方法,和call没有太大区别,这里就不赘述了。

这里我把函数和包含函数的对象在显式绑定和隐式绑定下的关系,比作买房和租房的区别。

因为这个

在隐式绑定下:函数sum只是暂时停留在包含对象的酒店,几天后可能会停留在另一家酒店

在显式绑定下:函数将获得“包含对象”中的永久居留权,并将一直“住在这里”

新绑定

【故事】这个组建了自己的家庭,生了很多孩子(很多对象都是通过构造函数new创建的)

当执行新操作时,将创建一个新的对象,这个构造函数将指向创建的新对象

function foo(a){ this . a=a;} var a1=new foo(1);var a2=new foo(2);var a3=new foo(3);var a4=new foo(4);console . log(a1 . a);//输出1 console . log(a2 . a);//output 2 console . log(a3 . a);//output 3 console . log(a4 . a);//输出4摘要

以上是边肖在JavaScript函数中引入的四种绑定形式。希望对大家有帮助。如果你有任何问题,请给我留言,边肖会及时回复你。非常感谢您对我们网站的支持!

版权声明:JavaScript函数中的四种绑定形式是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。