-
Notifications
You must be signed in to change notification settings - Fork 634
New issue
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 原理,并手写 bind 实现 #81
Comments
用apply实现bind?? |
面试的时候这样写会有什么问题吗?🙃 Function.prototype.myBind = function(context, ...args1) {
if(typeof this !== 'function') {
throw Error('error')
}
context = context ? Object(context) : Window
const currentFunc = this
return function(...args2) {
if(new.target) {
return new currentFunc(...[...args1, ...args2])
}
return currentFunc.apply(context, [...args1, ...args2])
}
} |
我也是直接返回的new self
|
Function.prototype.myBind = function (obj) {
if (typeof this !== 'function') {
throw new TypeError('bind is only work for Function')
}
let first = Array.prototype.slice.call(arguments, 1);//因为第一个参数是obj
let fn_ = function () { };
let fn = this;//调用bind的函数
fn_.prototype = fn.prototype;
const bindFn = function () {
let second = Array.prototype.slice.call(arguments);
fn.apply(this.constructor === fn ? this : obj, first.concat(second));
console.log(this);
}
bindFn.prototype = new fn_();
return bindFn;
} |
我不理解,修改后的版本,this.value不还是输出undefined吗... |
返回undefined 才是对的,修改之前的版本返回的是1,使用new 调用 this 应该是指向新创建的对象 undefined 才是对的~ |
不理解,this为何是bar函数 |
这是来自QQ邮箱的假期自动回复邮件。
您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。
|
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs)); |
if(new.target)是什么意思哇? |
@yysfwls 判断函数是否通过 new 调用。 |
这是来自QQ邮箱的假期自动回复邮件。
您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。
|
ES6的new.target语法,取巧了 |
|
|
这是来自QQ邮箱的假期自动回复邮件。
您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。
|
bind()
bind
方法与call / apply
最大的不同就是前者返回一个绑定上下文的函数,而后两者是直接执行了函数。来个例子说明下:
通过上述代码可以看出
bind
有如下特性:this
模拟实现:
但还有一个问题,
bind
有以下一个特性:来个例子说明下:
上面例子中,运行结果
this.value
输出为undefined
,这不是全局value
也不是foo
对象中的value
,这说明bind
的this
对象失效了,new
的实现中生成一个新的对象,这个时候的this
指向的是obj
。这个可以通过修改返回函数的原型来实现,代码如下:
注释1 :
this
指向实例,此时this instanceof fBound
结果为true
,可以让实例获得来自绑定函数的值,即上例中实例会具有habit
属性。this
指向window
,此时结果为false
,将绑定函数的this
指向context
注释2 :
prototype
为绑定函数的prototype
,实例就可以继承绑定函数的原型中的值,即上例中obj
可以获取到bar
原型上的friend
fNOP
作为中介,把fBound.prototype
赋值为空对象的实例(原型式继承),这是因为直接fBound.prototype = this.prototype
有一个缺点,修改fBound.prototype
的时候,也会直接修改this.prototype
;其实也可以直接使用ES5的Object.create()
方法生成一个新对象,但bind
和Object.create()
都是ES5方法,部分IE浏览器(IE < 9)并不支注意:
bind()
函数在 ES5 才被加入,所以并不是所有浏览器都支持,IE8
及以下的版本中不被支持,如果需要兼容可以使用 Polyfill 来实现详情可前往 深度解析bind原理、使用场景及模拟实现 查看
补充:柯里化
在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的。
这里定义了一个
add
函数,它接受一个参数并返回一个新的函数。调用add
之后,返回的函数就通过闭包的方式记住了add
的第一个参数。所以说bind
本身也是闭包的一种使用场景。柯里化是将
f(a,b,c)
可以被以f(a)(b)(c)
的形式被调用的转化。JavaScript 实现版本通常保留函数被正常调用和在参数数量不够的情况下返回偏函数这两个特性。The text was updated successfully, but these errors were encountered: