原文https://www.jianshu.com/p/3b69fb0d4c2f
我也不知道为什么只能显示一部分 好气哦 看原文吧
先分析下3个方法的作用
- 改变this的指向。
- 传入参数。
- call apply返回函数结果, bind 返回新函数
call
改变this的指向
首先我们知道,对象上的方法,在调用时,this是指向对象的。
let o = {
fn:function(){
console.log(this);
}
}
o.fn() // Object {fn: function}
// 函数原型上添加 myCall方法 来模拟call
Function.prototype.myCall = function(obj){
//我们要让传入的obj成为, 函数调用时的this值.
obj._fn_ = this; //在obj上添加_fn_属性,值是this(要调用此方法的那个函数对象)。
obj._fn_(); //在obj上调用函数,那函数的this值就是obj.
delete obj._fn_; // 再删除obj的_fn_属性,去除影响.
//_fn_ 只是个属性名 你可以随意起名,但是要注意可能会覆盖obj上本来就有的属性
}
下面测试一下
let test = {
name:'test'
}
let o = {
name:'o',
fn:function(){
console.log(this.name);
}
}
o.fn() // "o"
o.fn.call(test) // "test"
o.fn.myCall(test) // "test"
传入参数
- 最简单实现,用ES6
// 只需要在原来的基础上 用下拓展运算符 剩余运算符即可
Function.prototype.myCall = function(obj,...arg){
obj._fn_ = this;
obj._fn_(...arg);
delete obj._fn_;
}
//测试
let test = {
name:'test'
}
let o = {
name:'o',
fn:function(){
console.log(this.name, ...arguments); //这里把参数显示一下
}
}
o.fn(1,2,3) // "o" 1 2 3
o.fn.call(test,1,2,3) // "test" 1 2 3
o.fn.myCall(test,1,2,3) // "test" 1 2 3
// 没问题
- 用eval 方法
eval方法,会对传入的字符串,当做JS代码进行解析,执行。
Function.prototype.myCall = function(obj){
let arg = [];
for(let i = 1 ; i<arguments.length ; i++){
arg.push( 'arguments[' + i + ']' ) ;
// 这里要push 这行字符串 而不是直接push 值
// 因为直接push值会导致一些问题
// 例如: push一个数组 [1,2,3]
// 在下面