摘要:关于的指向的问题请参照我的学习笔记。那么在这里事实上都改变了函数方法被调用时的指向。那么回调函数在执行的时候指向还是。大家看完之后应该已经懂了把还是不懂的话在评论区留言,我给大家解答。
先从一个小题目开始吧:
要实现一个加法函数,这个时候向函数当中传递个数大于0的若干个整形数据,求所有这些数据的和。
Function.prototype.call
Function.prototype.apply
Function.prototype.bind
其中call方法:
var personA = { name: "XL", sayName: function (hobby){ console.log(this.name + " likes " + hobby); } }; personA.sayName("basketball"); // "XL likes basketball" var personB = { name: "xl" } personA.sayName.call(personB, "basketball"); // "xl likes basketball" personA.sayName.apply(personB, ["basketball"]); // "xl likes basketball"
call和apply的区别就在于传递方式的不同,call在接收指定参数的形式是someMethod.call(obj, arg1, arg2);而apply在接收指定参数时的形式是someMethod.apply(obj, [arg1, arg2]).或者someMethod.apply(obj, arg1),但是这个arg1必须是一个类数组对象
其实想要真正掌握call/apply包括bind方法,首先必须搞清楚当一个函数/方法被调用的时候this的指向问题。 关于this的指向的问题请参照我的学习笔记。
那么在这里call,apply,bind事实上都改变了函数/方法被调用时this的指向。
还是拿上面的例子来说:
personA.sayName(‘basketball’); //调用sayName()这个方法的对象是personA,因此sayName()内部的this指向就是personA对象
换一种写法
var sayName = personA.sayName("basketball"); //这里将sayName方法挂载到了window对象上,即window.sayName = person.sayName(); 这个时候调用sayName().此时this指向就是window对象
使用call/apply
personA.sayName.call(personB, "basketball"); //本来sayName方法的this指向是personA对象,但是调用call后,this对象指向了personB对象。
如果大家这种写法看不习惯,那就换种方式来看:
personA.sayName.call(personB, "basketball") ===> personB.sayName("basketball"); //从前面的一个形式变为后面一种形式,此时,sayName方法的this指向是personB对象了。
换一种方式书写后大家应该看的很清晰明了了吧?以后碰到call/apply调用的时候,换一种形式去理解,这样就很清晰了。
再比如大家经常看到的一种对于函数的arguments类数组对象的处理方式:
function fn() { var args = Array.prototype.slice.apply(arguments); //这里将arguments这个类数组对象转化为一个数组 } //咱们再来转化下: Array.prototype.slice.apply(arguments); ===>>> arguments.slice(); //因为arguments是类数组对象的原因,因此它可以直接调用slice方法;如果要截取数组的从第几位到第几位的数 Array.prototype.slice.apply(arguments, [0, 2]); ===>>> arguments.slice(0, 2);
握草,感觉编不下去了- -
其实将call/apply,换一种形式去看,是不是就和普通的方法调用一样一样的。
bind方法呢,起的作用和call,apply一样,都是改变函数/方法执行时,this的指向,确保这个函数/方法运行时this指向保持一致。
比如大家经常用到的setTimeout异步函数:
var person = { name: "XL", sayName: function() { setTimeout(function() { console.log(this.name); }, 0); } } person.sayName(); //最后输出: undefined
这是因为setTimeout()这个异步函数调用的时候,内部的回调函数this的指向是window.但是在window对象上并未挂载name属性,因此最后输出undefined.
添加一行代码
var name = "XLLLL"; var person = { name: "XL", sayName: function() { setTimeout(function() { console.log(this.name); }, 0); } } person.sayName(); //输出 ‘XLLLL’
为了避免在回调函数当中,this指向发生变化,所以大家都会这样处理:
var person = { name: "XL", sayName: function() { setTimeout(function() { console.log(this.name); }.bind(this), 0); //通过bind方法将this对象绑定为person。那么回调函数在执行的时候,this指向还是person。 } }
可以用下面这段代码来简单模拟下bind方法内部的操作:
Function.prototype.bind = function(obj) { var method = this; return function() { method.apply(obj, arguments); } }
还记得刚才给大家讲的将apply进行变换的形式吗?
Function.prototype.bind = function(obj) { var method = this; return function() { obj.method(arguments); } }
大家应该看到了bind和apply/call的区别了吧? bind方法是返回一个新的函数,但是这个函数比较特殊,这个函数的this对象已经被bind方法传入的第一个参数给绑定了.
比如我们可以使用bind方法来简写一个方法:
function fn() { var hasOwnKey = Function.call.bind(Object.hasOwnProperty); for(var key in obj) { if(hasOwnKey(obj, key)) { //xxxx } } }
唉,真的编不下去了。大家看完之后应该已经懂了把? - -
还是不懂的话在评论区留言,我给大家解答。
哦,一开始那个题目的一种写法
//要实现一个加法函数,这个时候向函数当中传递个数大于0的若干个整形数据,求所有这些数据的和。 function add() { return Array.prototype.reduce.call(arguments, function(n1, n2) { return n1 + n2; }); }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/80464.html
摘要:最近刚刚看完了你不知道的上卷,对有了更进一步的了解。你不知道的上卷由两部分组成,第一部分是作用域和闭包,第二部分是和对象原型。附录词法这一章并没有说明机制,只是介绍了中的箭头函数引入的行为词法。第章混合对象类类理论类的机制类的继承混入。 最近刚刚看完了《你不知道的 JavaScript》上卷,对 JavaScript 有了更进一步的了解。 《你不知道的 JavaScript》上卷由两部...
摘要:总结动态代理的相关原理已经讲解完毕,接下来让我们回答以下几个思考题。 【干货点】 此处是【好好面试】系列文的第12篇文章。文章目标主要是通过原理剖析的方式解答Aop动态代理的面试热点问题,通过一步步提出问题和了解原理的方式,我们可以记得更深更牢,进而解决被面试官卡住喉咙的情况。问题如下 SpringBoot默认代理类型是什么 为什么不用静态代理 JDK动态代理原理 CGLIB动态代理...
摘要:系统,扎实的语言基础是一个优秀的前端工程师必须具备的。第一个参数为调用函数时的指向,随后的参数则作为函数的参数并调用,也就是。和的区别只有一个,就是它只有两个参数,而且第二个参数为调用函数时的参数构成的数组。 系统,扎实的 javascript 语言基础是一个优秀的前端工程师必须具备的。在看了一些关于 call,apply,bind 的文章后,我还是打算写下这篇总结,原因其实有好几个。...
摘要:包中导出的默认是运行时构建。当然,我们期待的是只修改代码,不用重新运行命令,甚至不需要刷新浏览器即看到代码的改动效果,这时候需要新的插件来配置实现的热重载。 首先已经全局安装了node/vue/webpack; 新建文件夹demo4并初始化 cd demo4 npm init -y 这是页面会生成一个package.json文件。 安装webpack及相关插件 npm install ...
摘要:绑定书中提到在中,实际上并不存在所谓的构造函数,只有对于函数的构造调用。规则使用构造调用的时候,会自动绑定在期间创建的对象上。指向新创建的对象绑定比隐式绑定优先级高。 showImg(http://ww1.sinaimg.cn/large/005Y4rCogy1fstcwvzkjzj30sg0g0qqn.jpg); 前言 最近正在看《你不知道的JavaScript》,里面关于this绑...
阅读 3425·2019-08-30 15:44
阅读 744·2019-08-30 13:46
阅读 1948·2019-08-30 11:05
阅读 3292·2019-08-29 18:32
阅读 2125·2019-08-29 13:56
阅读 1270·2019-08-29 12:57
阅读 721·2019-08-28 18:21
阅读 1703·2019-08-26 12:16