记录call、apply、bind的源码
记录一下call、apply、bind的源码,然后从根本上明白其用法。 都知道call、apply与bind的用法,call(this,...arguments)、apply(this,[arguments])、var fn = bind(this,...arguments);fn(...newarguments); call和apply都是立即执行,只是传参数形式不一样,call参数一字排开,apply参数是数组,bind绑定之后返回一个新函数但是并不立即执行,需要额外调用的时候才执行,并且,绑定的时候可以额外传参数,执行的时候也可以额外传参数。 call和apply执行的本质是,往要绑定的context对象下添加该函数,然后执行,最后将属性删除。当context值为null,或者undefined时,非严格模式下,它将替换为window或者global全局变量。 Function.prototype.call = function (context) { var context = context || window; context.fn = this; var args = []; for(var i = 1,len = arguments.length; i < len; i++) { args.push(‘arguments[‘ + i + ‘]‘); } var result = eval(‘context.fn(‘ + args +‘)‘); delete context.fn return result; } ? Function.prototype.apply = function (context,arr) { var context = Object(context) || window; context.fn = this; var result; if (!arr) { result = context.fn(); } else { var args = []; for (var i = 0,len = arr.length; i < len; i++) { args.push(‘arr[‘ + i + ‘]‘); } result = eval(‘context.fn(‘ + args + ‘)‘) } delete context.fn return result; } bind因为不会立刻执行,而是返回一个函数,一般情况下,该函数执行时的this指向绑定的对象。而麻烦的是JS中该函数还可以通过new来实例化,而实例化之后的this要指向新创建的对象,不能再跟着绑定的对象走了,所以该函数内部对this进行了额外处理,看它是否是通过new创建的实例,如果是通过new创建的实例,this对象指向新创建的new对象实例。 if (!Function.prototype.bind) { Function.prototype.bind = function (oThis) { if (typeof this !== "function") { throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments,1),fToBind = this,fNOP = function () {},fBound = function () { return fToBind.apply(this instanceof fNOP ? this : oThis || this,aArgs.concat(Array.prototype.slice.call(arguments))); }; fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; }; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |