We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bind方法,顾名思义,就是绑定的意思,到底是怎么绑定然后怎么用呢?
我们首先来看一下MDN中对于bind的定义以及bind的语法。
bind() 方法创建一个新的函数,在调用时设置this关键字为提供的值。并在调用新函数时,将给定参数列表作为原函数的参数序列的前若干项。
function.bind(thisArg[, arg1[, arg2[, ...]]])
参数:
返回值:
let foo = { value: 1 }; function bar(arg) { console.log(this.value,arg); } // 返回了一个函数 let bindFoo = bar.bind(foo,2); bindFoo(); // print: 1 2
先考虑第一个特点,返回一个新函数
Function.prototype.myBind = function() { let func = this; return function(...args){ return func(...args); } }
再考虑第二个特点,为新函数指定 this
我们知道可以通过使用 apply 或 call 来为函数指定 this , 在这里我们用 apply 来实现
Function.prototype.myBind = function(thisArg) { let func = this; return function(...args){ return func.apply(thisArg,args); } }
再考虑第三个特点,为新函数指定参数
对于参数来说,有很多不确定性,我们可以在 bind 的时候指定参数,也可以在新函数中指定参数,那具体的规则是什么呢?
来看关于 bind 函数,参数的一个例子
let fn = function(a,b){ console.log(a,b); } let fn1 = fn.bind(null); fn1('a','b'); // print: a b let fn2 = fn.bind(null,1); fn2('a','b'); // print: 1 a let fn3 = fn.bind(null,1,2) fn3('a','b'); // print: 1 2
由此我们得出这样的结论:
bind 函数可以在指定 this 的同时,同时指定为新函数预设参数,当然也可以不预设参数。
接下来我们来实现预设参数的特性
Function.prototype.myBind = function(thisArg,...args) { let func = this; return function(){ //将 arguments 转换为 数组 并与 myBind 函数的 args 合并 let _args = [...args,...Array.prototype.slice.call(arguments)]; return func.apply(thisArg,_args); } }
那么我们模拟实现bind完成了么? NO~! bind 还有一些隐藏特性~
来自MDN的解释: 绑定函数自动适应于使用 new 操作符去构造一个由目标函数创建的新实例。当一个绑定函数是用来构建一个值的,原来提供的 this 就会被忽略。不过提供的参数列表仍然会插入到构造函数调用时的参数列表之前。
我们来用一个例子来解释:
function Point(x,y) { this.x = x; this.y = y; } Point.prototype.print = function() { console.log(this.x,this.y); } let NewPoint = Point.bind({},1,2) new NewPoint().print(3,4); // print: 1 2
从这个例子,我们可以看到,如果 bind() 返回的函数用作构造函数:
依照上面的规则,简单修改下我们的模拟代码:
Function.prototype.myBind = function(thisArg,...args) { let func = this; //最终返回的新函数 let fBound = function(){ //将 arguments 转换为 数组 并与 myBind 函数的 args 合并 let _args = [...args,...Array.prototype.slice.call(arguments)]; //当作为构造函数执行时,传递的this为当前实例,否则为传入的this let context = this instanceof fBound ? this : thisArg; return func.apply(context,_args); } //将新函数的原型链重置为原函数的原型链 //作为构造函数执行时,返回的对象获取了原函数原型链上的所有属性及方法 fBound.prototype = func.prototype; return fBound; }
在上文中的这段代码:
fBound.prototype = func.prototype;
但这样做,引入了一个新的问题,如果我们修改 fBound.prototype 时,也会同时修改原函数的 prototype
所以我们考虑用一个空函数来进行中转:
Function.prototype.myBind = function(thisArg,...args) { let func = this; //最终返回的新函数 let fBound = function(){ //将 arguments 转换为 数组 并与 myBind 函数的 args 合并 let _args = [...args,...Array.prototype.slice.call(arguments)]; //当作为构造函数执行时,传递的this为当前实例,否则为传入的this let context = this instanceof fBound ? this : thisArg; return func.apply(context,_args); } //中转函数 let fNOP = function(){} fNOP.prototype =func.prototype; fBound.prototype = new fNOP(); return fBound; }
我们知道对于函数来说,函数有一个属性 length 代表这个函数形参的个数
let fn = function(a,b,c,d) {}; console.log(fn.length); // print : 4
而对于 bind() 返回的函数对象的 length 属性是绑定函数的形参个数减去绑定实参的个数(length 不能小于零)
let fn = function(a,b,c,d) {}; let newFn = fn.bind(null,1,2); console.log(newFn.length); // print: 2
简单实现:
Function.prototype.myBind = function(thisArg,...args) { let func = this; //最终返回的新函数 let fBound = function(){ //将 arguments 转换为 数组 并与 myBind 函数的 args 合并 let _args = [...args,...Array.prototype.slice.call(arguments)]; //当作为构造函数执行时,传递的this为当前实例,否则为传入的this let context = this instanceof fBound ? this : thisArg; return func.apply(context,_args); } //中转函数 let fNOP = function(){} fNOP.prototype =func.prototype; fBound.prototype = new fNOP(); //修改新函数的length属性 fBound.length = Math.max(0,func.length - args.length) return fBound; }
The text was updated successfully, but these errors were encountered:
6666666
Sorry, something went wrong.
No branches or pull requests
模拟实现 bind
什么是 bind
bind方法,顾名思义,就是绑定的意思,到底是怎么绑定然后怎么用呢?
我们首先来看一下MDN中对于bind的定义以及bind的语法。
bind 的定义:
bind 的语法:
参数:
返回值:
一个简单的例子
对bind的简单归纳
开始实现我们的 bind 函数
先考虑第一个特点,返回一个新函数
再考虑第二个特点,为新函数指定 this
我们知道可以通过使用 apply 或 call 来为函数指定 this , 在这里我们用 apply 来实现
再考虑第三个特点,为新函数指定参数
对于参数来说,有很多不确定性,我们可以在 bind 的时候指定参数,也可以在新函数中指定参数,那具体的规则是什么呢?
来看关于 bind 函数,参数的一个例子
由此我们得出这样的结论:
bind 函数可以在指定 this 的同时,同时指定为新函数预设参数,当然也可以不预设参数。
接下来我们来实现预设参数的特性
那么我们模拟实现bind完成了么? NO~! bind 还有一些隐藏特性~
作为构造函数使用的绑定函数
我们来用一个例子来解释:
从这个例子,我们可以看到,如果 bind() 返回的函数用作构造函数:
依照上面的规则,简单修改下我们的模拟代码:
在上文中的这段代码:
但这样做,引入了一个新的问题,如果我们修改 fBound.prototype 时,也会同时修改原函数的 prototype
所以我们考虑用一个空函数来进行中转:
最后一点小问题
我们知道对于函数来说,函数有一个属性 length 代表这个函数形参的个数
而对于 bind() 返回的函数对象的 length 属性是绑定函数的形参个数减去绑定实参的个数(length 不能小于零)
简单实现:
The text was updated successfully, but these errors were encountered: