JavaScript疑惑之call、replay与bind方法 您所在的位置:网站首页 individually和separately的区别 JavaScript疑惑之call、replay与bind方法

JavaScript疑惑之call、replay与bind方法

#JavaScript疑惑之call、replay与bind方法| 来源: 网络整理| 查看: 265

一直以来,对于JavaScript中的call,apply以及bink都不是很清楚,只是知道有这么几个东西,但都没有去仔细研究。最近在用JavaScript实现常见数据结构,看书时里面有提到call,正好借此好好研究一些这三个方法。随便一搜,网上相关的文章很多,但是越是这样大家都关注的问题,肯定说明其重要性和一定的难度。因此,对于网上参差不齐的回答,我不敢轻信,因为一开始所摄入的信息对于陌生问题在脑中的定势是非常重要的。

三者是干嘛的

要回答清楚这个问题,那就说明已经对此清楚了,显然我现在还回答不了。目前的理解是call、replay是同一个东西,而bind是另一个东西。MDN中的说明:

The call() allows for a function/method belonging to one object to be assigned and called for a different object. call() provides a new value of this to the function/method. With call(), you can write a method once and then inherit it in another object, without having to rewrite the method for the new object. //调用父构造函数 function Product(name, price) { this.name = name; this.price = price; } function Food(name, price) { Product.call(this, name, price); this.category = 'food'; } //同class中的继承 class Food extend Product { constructor(name,price) { super(name, price); this.category = 'food'; } } //调用函数并指定上下文的‘this’ function greet() { var reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' '); console.log(reply); } var obj = { animal: 'cats', sleepDuration: '12 and 16 hours' }; greet.call(obj); // cats typically sleep between 12 and 16 hours

而call和replay则是同一个东西:区别是传入参数书写的实行不一样,仅此而已。

 While the syntax of this function is almost identical to that of apply(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments.

call和apply

从一个简单的例子进行说明。首先,定义一个对象obj,对象非常简单,只有一个属性num。其次,定义一个函数sum,里面可以传入一个参数a。问题在于函数计算的是this.num + a,很显然,在函数里面出现this会有问题,因为对于sum函数来说,this.num是未知的。

let obj = {num: 1}; function sum(a) { return this.num + a; } let result = sum(2); console.log(result) //NaN

我们是想算obj的num属性值(即1)加上2的和,但是但我们调用sum函数时,函数中的this.num是未知的,要解决这个问题,首先用call。

call let result = sum.call(obj, 2); console.log(result); //3

这里成功输出了我们想要的结果,就是obj.num的值加上我们传入的参数2,输出3。

//方式一: let obj = {num: 1}; function sum(a) { return this.num + a; } let result = sum.call(obj, 1) //方式二: function sum(a) { return 1 + a; } let result = sum(1);

上面的两种方式的代码,方式二是我们最常见的,非常容易理解,即计算一个数加上1等于多少;实际上,方式一也是相同的效果。MND中对call的解释,The call() method calls a function with a given this value and arguments provided individually。”given this value”讲得有点不容易理解。这里暂且不去管。

let result = sum.call(obj, 1);

sum函数中没有this.num这个值,因此需要call obj对象,即“借用”obj对象中的name属性(obj.name)。但是在代码中并不是obj.num ,而是this.num,关于this,也是一个复杂的话题。

let obj = {num: 1} function sum(a) { return ojb.num + a } let result = sum(2)

这段代码显然是没有任何问题的,因为这里的obj.num对于sum函数而言是一个已知量,因为sum能够获取出于全局作用域的obj对象。

let obj = {num: 1} function sum(a) { return this.num + a } let result = sum.call(obj, 2)

这里call的作用就相当于将sum函数中的this.name变成了obj.num。call即可理解成“借用”this的num属性。因为call的是obj对象,所以this指的就是obj。一句话形象的描述上面发生的过程,我(sum函数)要计算this.num+a的值,a是我的参数,我能知道,但是里面的this.num我不知道是什么,具体来说我不知道是哪个对象的num属性。我(sum函数)通过call对象obj,找obj对象(因为他有num属性),即我借用obj对象的属性值,我就可以算出obj.num+a的值了。

apply

前面讲了,call和apple是同一个东西,因为两者只是在语法(写法)上的区别,仅此而已。

let obj = {num: 1}; function sum(a, b, c) { return this.num + a + b + c; }

这里我要计算多个数的和,很容易知道,sum函数知道a,b,c是什么(因为调用sum的使用要传给他),但是其中的this.num是个未知量,sum需要向其他对象“借用”,下面用call和replay来实现。

let result1 = sum.call(obj, 2, 3, 4); //1+2+3+4=10 let result2 = sum.apply(obj, [2, 3, 4]); //1+2+3+4=10

两者都是计算this.num+a+b+c的和,也都是“借用”obj对象的obj.num,两者实现的效果完全相同,只是写法上的不同而已。apply方法传入的参数是obj(借用的对象)以及一个数组

//上面的apply方法代码也可以这么写 let arr = [2, 3, 4]; let result2 = sum.apply(obj, arr];

至此,应该大概是知道call和apply是个什么东西了,即“借用”别的对象。(这种“借用”的表述不严谨,仅个人目前理解的观点)

bind

在React中采用class component时,bind (this)是必不可少的,但是此前也就照着这个样式去写,没有去深究其究竟意味着什么。先来看MND中的关于bind的说明:The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

最重要的一点是,bind方法返回的是一个函数,这是其与call和apply的不同。

let obj = {num: 1}; function sum(a, b, c) { return this.num + a + b + c; } const newFn = sum.bind(obj);

在控制台中,我们看到newFn是一个函数,当传入参数2,3,4之后,得出10(1+2+3+4),很明显,newFn这个函数中的this.num值为1,即调用newFn函数时,成功“借用”了ojb对象的num属性(obj.num=1)。

创建绑定函数

let cat = { sound: '喵~', talk: function () { console.log(this.sound); } }; cat.talk() //“喵~”

JavaScript中的函数是一个对象,同时也是一个值,可以被赋值给其他变量,这在JavaScript中是很正常的事情,就像下面这样操作,把cat.talk方法(函数)赋值给新的变量catTalk,此时catTalk也是一个函数。

let catTalk = cat.talk;

但执行catTalk函数时,输出的是undefined,因为catTalk函数中并没有this.sound(存在与cat对象中)。自然,这里会输入undefined。bind能够将cat对象中的sound属性绑定给函数。

let cat = { sound: '喵~', talk: function () { console.log(this.sound); } }; catTalk = cat.talk.bind(cat); catTalk(); //喵~ 参考资料 视频:javaScript call apply and bind


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有