-
Notifications
You must be signed in to change notification settings - Fork 1
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
call、apply和bind的实现 #16
Comments
你好,你的 apply 实现代码有问题。
|
@Lamborshea 已修正 谢谢~ |
感谢分享 |
@zhangyuexin 不客气 |
看了之后很喜欢,然后自己对 call 的最后实现稍微做了修改,欢迎各位也能指点指点。 Function.prototype.newCall = function (context, ...args) {
if (context === null || context === undefined) {
context = window;
} else {
context = Object(context);
}
let fn = Symbol();
context[fn] = this;
context[fn](...args);
delete context[fn];
};
let person = {
name: "Jim"
};
function sayHi(age, sex) {
console.log(this.name, age, sex, this);
}
sayHi.newCall(person, 25, "male"); |
我同意这个 传入null this直线window |
我自己对bind做了一下修改 Function.prototype._bind = function (ctx) {
const origin = this;
const Mid = function () {};
const args = [].slice.call(arguments, 1);
const newFn = function () {
const args1 = [...arguments].concat(args);
return origin.apply(this instanceof newFn ? this : ctx, args1);
};
Mid.prototype = this.prototype;
newFn.prototype = new Mid();
return newFn;
}; |
Function.prototype.myBind = function (context, ...args) {
let self = this
function fn(...args) {
context.fun = self
context.fun(...args)
}
return function () {
return fn(...args)
}
} |
同意 @samualle 的观点,因为作者写的代码当传入 下面是我的实现 Function.prototype.fakeCall = function(target, ...params) {
if (target == null) {// undefined || null
target = window
} else if (typeof target !== 'object') {
target = Object.create(null)
}
const key = Symbol()
target[key] = this
target[key](...params)
delete target[key]
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
因为关乎到了this指向的问题,call、apply和bind的用法可以说是老生常谈了。这篇文章的主要作用是利用js原生方法对三个方法进行实现,升入了解其中的原理,对相关知识点有更好的掌握。
call与apply
简单介绍:call和apply方法都是使用一个指定的this值和对应的参数前提下调用某个函数或方法。区别则在于call是通过传多个参数的方式,而apply则是传入一个数组。
举个例子:
模拟实现
思路:在JavaScript中的this指向说到了:函数还可以作为某个对象的方法调用,这时this就指这个上级对象。也就是我们平时说的,谁调用,this就指向谁。所以实现的方法就是在传入的对象中添加这么一个方法,然后再去执行这个方法。为了保持对象一直,在执行完之后再把这个对象给删除了。是不是很简单^-^。
初体验:
这样就完成了基础版本的实现,但是如果说有传参数呢?
所以我们可以进行优化一下,因为传入的参数数量是不确定的,所以我们可以从Arguments对象中去获取,这个比较简单。问题是参数是不确定的,我们如何传入到我们要执行的函数中去呢 ? 这里我们有两种选择:一种是通过eval拼接的方式,另一种就要用到es6了。
体验升级(eval版本):
体验升级(ES6版本):
让然ES6的方法还可以不用到arguments就能实现
ES6版本再升级:
这样我们基本上实现了call的功能,但是还是存在一些隐患和区别。
当对象本身就有fn这个方法的时候,就有大问题了。
当call传入的对象是null的时候,或者其他一些类型的时候,函数会报错。
终极体验:
实现了call之后,apply也是同样的思路。
apply实现:
bind
bind也是函数的方法,作用也是改变this执行,同时也是能传多个参数。与call和apply不同的是bind方法不会立即执行,而是返回一个改变上下文this指向后的函数,原函数并没有被改变。并且如果函数本身是一个绑定了 this 对象的函数,那 apply 和 call 不会像预期那样执行。
初体验:
加入参数:
The text was updated successfully, but these errors were encountered: