Javascript中绑定的3种方法及其比较

介绍

这可以说是Javascript最吸引人的特性。学习这个过程的第一步是要理解,这既不是函数也不是函数区域,这实际上是在函数被调用时发生的绑定,它指向的是完全依赖于函数被调用的位置。



为什么需要绑定这个

这指的是当前的上下文,这很容易在无意中改变:


这是全局信息;
var obj = { {
信息:这是当地的信息',
发生:发生
}
功能getInfo(){
console.log(的信息);
}
Obj.getInfo() / /这是本地信息

对于发生的当前上下文环境() / /这是全球信息的修改


在上面的示例中,我们创建一个对象时发生的属性,在参考GetInfo全球范围内,其作用是在当前上下文中打印信息的价值,当我们使用obj.getinfo拨打电话,它会打印出对象内部的信息价值,这指向对象。当我们使用全局函数,它打印出的信息变量的值在全球环境中,当这个点的全局对象。

这个例子告诉我们:

1,功能相同,通话方式不同,方向也会有所不同,结果也会有所不同。



2。当一个对象中的属性的值是一个引用类型时,这一点不会总是绑定到原始对象。



其次,有一个疏忽造成的损失:


这是全局信息;
var obj = { {
信息:这是当地的信息',
GetInfo:功能getInfo(){
console.log(的信息);

无功getinfo2 =功能getinfo2(){
console.log(的信息);
}
getinfo2();
}
}
Obj.getInfo();

这是本地信息。
这是全局信息。


在上面的例子中,发生在一个方法定义的目标对象,在方法定义了一个新的功能,也希望得到的价值最外层对象的信息的性质,但它没有,这是窗口对象错点的功能,从而导致误差。

这个解决方案很简单,在外层定义一个变量,将当前的词法存储在这个范围内的位置上指出,根据变量范围之间的关系,函数可以访问变量后得到真实点的上函数,内部这个。


这是全局信息;
var obj = { {
信息:这是当地的信息',
GetInfo:功能getInfo(){
console.log(的信息);

var =;这将保存到外部变量
无功getinfo2 =功能getinfo2(){
console.log(自我。信息); / /指向外部变量代表
}
getinfo2();
}
}
Obj.getInfo();

这是本地信息。
这是本地信息。


然而,它也会带来一些问题,自变量等于重新指一个obj对象,所以你可能在不经意间一些时间修改整个对象,但是当需要得到这个环境的时候,你需要声明多个变量,不利于管理。

有一些方法可以在当前环境中绑定上下文,而无需声明类似于自身的变量,以确保编程内容的安全性。

如何绑定这个



1。电话,应用



调用和应用是两个函数定义在function.prototype,他们的作用是修改,功能执行的背景下,对这一点。

在呼叫的情况下,这anotherfun想输出局部的东西修改:



无功anotherfun = obj.getinfo;
anotherfun.call(obj) / /这是本地信息


函数调用的参数:

function.prototype.call(上下文{,论证1,论证2 })



Function.prototype.apply(上下文{ } },{参数)



从这里您可以看到,调用和应用的第一个参数是必须的,接受修改后的上下文,第二个参数是可选的,它们的区别是,从第二个参数开始调用,接受传入函数函数的调用是一个单独的,这是应用接受传入数组。


添加函数(num1,num2,小键盘数字3){
返回num1 + num2 +小键盘数字3;
}
add.call(null,10, 20, 30); / / 60
add.apply(null,{ 10, 20, 30 }); / / 60


当接受上下文未定义或null时,它将自动作为全局对象进行修改,这是上述示例中的窗口。

2。function.prototype.bind结合使用



在新的function.prototype ES5的绑定方法,它接受一个上下文绑定对象,并返回一个相同的函数调用,它也可以在后面添加参数,达到腐熟的功能。


Function.prototype.bind(上下文{,论证1,论证2 })
/ /功能承载部分
添加函数(num1,num2){
返回num1 + num2;
}
无功anotherfun = window.add.bind(窗,10);
AnotherFun(20); / / 30


同时,他返回一个函数的副本,并将函数永久绑定到传入上下文中。



无功anotherfun = obj.getinfo.bind(obj)
AnotherFun(); / /这是本地信息


polyfill



polyfill是向下兼容的解决方案,以及如何在旧的浏览器不支持ES5使用绑定的,所以我们需要重写一个绑定方法用老方法。


如果(!函数.原型.绑定){
function.prototype.bind =功能(obj){
var =;
返回函数(){
Self.call(obj);
}
}
}


上述措辞可以返回一个函数,和上下文参数的修正,但并没有实现级联的一部分。



function.prototype.bind =功能(obj){
var args = array.prototype.slice.call(参数1);
第一个参数记录所有传入

var =;
返回函数(){
Self.apply(obj,args.concat(array.prototype.slice.call(参数)));
}
}


当绑定用于绑定时,即不再调用,应用程序用于纠正此指向,因此绑定绑定也称为硬绑定。

三.使用新关键字进行绑定



在js中,函数有两种调用,一种是直接调用,另一种是通过新关键字进行构造调用。


函数fun(){ console.log(函数调用)}
直接调用
有趣的()函数
调用结构
var obj =新的乐趣() / /函数调用


常用的调用和使用新关键字的构造调用有什么区别

确切地说,新关键字只在调用函数的基础上增加了几个步骤,其中包括将这个指针修改为返回的对象。


var a=5;
功能乐趣(){
这个= 10;
}
var obj =新的乐趣();
Obj。 / / 10


几种绑定方法的优先级比较



下面的示例用于比较几个绑定状态的优先级权重


var obj1 = { {
信息:这是obj1
(GETINFO:)= console.log(的信息)
}

var obj2 = { {
信息:这是obj2
(GETINFO:)= console.log(的信息)
}


1。调用、应用和默认指向比较



首先,很明显,使用调用和应用将高于使用频率的直接调用优先级。


obj1.getinfo() / /这是obj1
obj2.getinfo() / /这是obj2
obj1.getinfo.call(obj2) / /这是obj2
Obj2.getInfo.call (obj1) //this is obj1


使用电话和申请比使用新

这会是个问题,因为我们不能运行的代码像新的function.call(东西)。所以,我们将返回一个新的功能,通过绑定的方法,然后判断优先的新。


var obj = { }
函数(数字){
this.num =民;
}

无功setnum = foo.bind(obj);
(10)setnum;
obj.num / / 10

var obj2 =新setnum(20);
obj.num / / 10
obj2.num / / 20


通过这个例子,我们可以看到当使用新构造调用时,它将返回一个新对象并将其修改为这个对象,但是它不会改变对象的内容。

那么问题来了,和绑定polyfill我们写上面显然是不能够的。在MDN,有绑定polyfill方法,其方法如下:


如果(!函数.原型.绑定){
function.prototype.bind =功能(o){
如果(typeof这!=函数){
抛出TypeError(function.prototype.bind——
试图绑定的是不可调用的;
}
无功aargs = array.prototype.slice.call(参数1),
这ftobind =,
浮点空操作=函数(){ },
fbound =函数(){
返回ftobind.apply(这是浮点空操作)
本:这本| |,
AArgs.concat(array.prototype.slice.call(参数)));
};
fnop.prototype = this.prototype;
fbound.prototype =新的浮点空操作();
返回fbound;
};
}


上述polyfill首先决定是否需要绑定的对象是一个函数,并防止一些从一个功能造成未知的错误使用时function.prototype.bind.call(东西)。之后,该fbound函数需要返回,返回fbound继承。

例外情况



当然,在某些情况下,指针上有一些意外。

箭头功能



6添加一个函数的定义,定义= > 功能,在它的指针,这是不会改变的,总是指向的词法范围的最外层。


var obj = { {
Num:1,
GetNum:函数(){
返回函数(){
此损失
console.log(这个数字);
这个到窗口
}
}
}
Obj.getNum()()(); / /未定义

var obj2 = { {
Num:2,
GetNum:函数(){
(回报率)= console.log(这个数);
箭头/功能外getnum约束内,这叫外部对象
}
}
obj2.getnum()()(); / / 2


软约束



上面提供的绑定方法能直接通过强迫,不再进行电话申请。如果我们想结合的效果,但我们可以让两个修正函数通过调用和应用,这个时候我们需要重写一个基于function.prototype方法。我们称之为软绑定。


如果(!函数原型。softbind){
function.prototype.softbind =功能(obj){
var =;
var args = array.prototype.slice.call(参数1);
返回函数(){
返回(self.apply(这个= | |!(窗全球| |))
Obj:这,
Args.concat(array.prototype.slice.call(参数)));
}
}
}


绑定,调用细化



当我们需要将一个伪数组元素为平天正常的数组元素,我们经常使用的array.prototype.slice方法,就像上面的例子,把争论的对象变成一个真正的数组对象,并使用array.prototype.slice.call(参数)来转换它。然而,它太长了,每一次使用这种方法繁琐。所以有时候我们写这:


var片= array.prototype.slice;
切片(参数);
错误


同样的问题出现在下面:


VaR体系= document.queryselectorall;
QSA(某物);
错误


在内置的切片和querySelectorAll方法出现上述问题,这是在内部使用。当我们简单地引用时,这将成为运行时的全局环境窗口,当然,它会导致错误。


VaR体系= document.queryselectorall.bind(文档);
QSA(某物);


同样,因为调用和应用也是一个函数,因此可以在它们上调用绑定方法。因此,返回函数本身的副本具有修正指针的功能。


var片= Function.prototype.call.bind(阵列。原型。片);
切片(参数);


总结

以上就是本文的全部内容。希望本文的内容能给大家的学习或工作带来一定的帮助。如果有任何疑问,你可以留言。