You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
bind 还有一个特点,就是:一个绑定函数也能使用 new 操作符创建对象:这种行为就像把原函数当成构造器。提供的 this 值被忽略,同时调用时的参数被提供给模拟函数。
也就是说,当 bind 返回的函数作为构造函数的时候,bind 时指定的 this 值会失效,但传入的参数依然生效。
所以我们可以通过修改返回的函数的原型来实现:
Function.prototype.mybind=function(context){varself=this;varargs=Array.prototype.slice.call(arguments,1);varfBound=function(){varbindArgs=Array.prototype.slice.call(arguments);// 当作为构造函数时,this 指向实例,此时结果为 true,将绑定函数的 this 指向该实例,可以让实例获得来自绑定函数的值// 以上面的是 demo 为例,如果改成 `this instanceof fBound ? null : context`,实例只是一个空对象,将 null 改成 this ,实例会具有 habit 属性// 当作为普通函数时,this 指向 window,此时结果为 false,将绑定函数的 this 指向 contextreturnself.apply(thisinstanceoffBound ? this : context,args.concat(bindArgs));};// 修改返回函数的 prototype 为绑定函数的 prototype,实例就可以继承绑定函数的原型中的值fBound.prototype=this.prototype;returnfBound;};
优化:
Function.prototype.mybind=function(context){if(typeofthis!=="function"){thrownewError("Function.prototype.bind - what is trying to be bound is not callable");}varself=this;varargs=Array.prototype.slice.call(arguments,1);varfNOP=function(){};varfBound=function(){varbindArgs=Array.prototype.slice.call(arguments);returnself.apply(thisinstanceoffNOP ? this : context,args.concat(bindArgs));};fNOP.prototype=this.prototype;fBound.prototype=newfNOP();returnfBound;};
functionPerson(name,age){this.name=name;this.age=age;this.habit="Games";}Person.prototype.getName=function(){console.log("I am "+this.name);};varperson1=newPerson("Yang","27");console.log(person1.name);// Yangconsole.log(person1.habit);// Gamesperson1.getName();// I am Yang
由上可知,实例 person1 可以:
访问到 Person 构造函数里的属性
访问到 Person.prototype 中的属性
初步实现
分析:
因为 new 的结果是一个新对象,所以在模拟实现的时候,我们也要建立一个新对象,这个新对象会具有构造函数里的属性。
functionobjectFactory(){varobj=newObject();varConstructor=[].shift.call(arguments);obj.__proto__=Constructor.prototype;varret=Constructor.apply(obj,arguments);returntypeofret==="object" ? ret : obj;}
call 和 apply 的模拟实现
call
call()
在使用一个指定的 this 值和若干个指定的参数值的前提下,调用某个函数或方法。该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组。使用 call 方法调用函数并且指定上下文的 'this'
使用 call 方法调用父构造函数
所以我们模拟的步骤可以分为:
第一版:绑定 this
第二版:给定参数
第三版:传参为 null 和返回结果
第四版:考虑 context,以及 context.fn 的可能性
apply
apply()
同call()
,只不过将多个参数值,以数组的形式传入而已。用 apply 将数组添加到另一个数组:
使用 apply 和内置函数:
原文链接:JavaScript 深入之 call 和 apply 的模拟实现
bind 的模拟实现
创建绑定函数
配合 setTimeout
由此我们可以首先得出 bind 函数的两个特点:
第一版:返回函数
第二版:传参
第三版:构造函数效果
bind 还有一个特点,就是:一个绑定函数也能使用 new 操作符创建对象:这种行为就像把原函数当成构造器。提供的 this 值被忽略,同时调用时的参数被提供给模拟函数。
也就是说,当 bind 返回的函数作为构造函数的时候,bind 时指定的 this 值会失效,但传入的参数依然生效。
所以我们可以通过修改返回的函数的原型来实现:
优化:
那别忘了做个兼容:
原文链接:JavaScript 深入之 bind 的模拟实现
new 的模拟实现
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象类型之一。
由上可知,实例 person1 可以:
初步实现
分析:
因为 new 的结果是一个新对象,所以在模拟实现的时候,我们也要建立一个新对象,这个新对象会具有构造函数里的属性。
实例的
__proto__
属性会指向构造函数的prototype
,也正是因为建立起这样的关系,实例可以访问原型上的属性。返回值效果实现
需要判断返回的值是不是一个对象,如果是一个对象,我们就返回这个对象,如果没有,我们该返回什么就返回什么
原文链接:JavaScript 深入之 new 的模拟实现
类数组对象与 arguments
类数组对象从读写、获取长度、遍历三个方面看,和数组貌似是一样的,但是无法直接使用数组的方法,需要借助 call 或 apply:
类数组转数组
Arguments
Arguments
对象只定义在函数体中,包括了函数的参数和其他属性。在函数体中,arguments 指代该函数的 Arguments 对象。Arguments 对象的 length 属性,表示实参的长度。
Arguments 对象的 callee 属性,通过它可以调用函数自身。
将参数从一个函数传递到另一个函数:
使用 ES6 的
...
运算符,我们可以轻松转成数组。arguments 的应用其实很多,如果要总结这些场景的话,暂时能想到的包括:
原文链接:JavaScript 深入之类数组对象与 arguments
The text was updated successfully, but these errors were encountered: