call函数

初学js,实践一下call的功能实现。
最初的想法是不改变Function的prototype中的call(),其实在这里面添加一个名字不同的函数就够了。
用自己的构造函数构造一个实例来完成。但是函数构造实例是一个对象啊。尝试里面写个函数试试。

//实现call函数 
let obj = {
    name: "OBJ"
};
let Fn = function(){
    // console.log(this);
    // this.name = "A";
    this.fn = function(a,b){
        console.log(this.name);
        console.log(a,b);
    }
}
/*
* call 的要求 ,1、改变this指向一个实参;2、其余实参传入并执行。
*/
Fn.prototype.call = function(){
    let otherParams = [...arguments];//arguments是一个类数组。就算是一个数组,也尽量不要破坏arguments的原内容
    let param1 = otherParams.shift();
    // console.log(otherParams);
    // console.log(param1);
    //fn1.call时,this指向fn1。
    this.fn.this = param1;//f1.fn代表的是存放代码的堆空间,改变这个堆空间的this与代码执行无关
    //this.fn().this = param1;//this.fn()代表的是函数执行的返回值,报错,返回undefined没有this属性。所以考虑用闭包。
    this.fn(...otherParams);
}

let fn1 = new Fn();//{fn:xxxfff111}
// fn1.fn();
// console.log(fn1.name);
fn1.call(obj,12,13);

打印:
undefined
12 13

emm,闭包走起。

let obj = {
    name: "OBJ"
};
let Fn = function(){
    fn = function(a,b){
        console.log(this);
        console.log(this.name);
        console.log(a,b);
    }
    return fn;
}

/*
* call 的要求 ,1、改变this指向一个实参;2、其余实参传入并执行。
*/
Fn.prototype.call = function(){
    let otherParams = [...arguments];//arguments是一个类数组。就算是一个数组,也尽量不要破坏arguments的原内容
    let param1 = otherParams.shift();
    // console.log(otherParams);
    // console.log(param1);
    //fn1.call时,this指向fn1。
    this.fn.this = param1;//f1.fn代表的是存放代码的堆空间,改变这个堆空间的this与代码执行无关
    //this.fn().this = param1;//this.fn()代表的是函数执行的返回值,报错,返回undefined没有this属性。所以考虑用闭包。
    this.fn(...otherParams);
   
}

let fn1 = new Fn();//{fn:xxxfff111} 现在new一个实例,其实被替代了。
// fn1.fn();
// console.log(fn1.name);
fn1.call(obj,12,13);
打印:
Object {name: "OBJ"}
OBJ
12 13

成功了?
但是有一个问题,在new一个实例时,__proto__是什么时候被更改指向的呢?于是console.log(fn1.__proto__===Fn.prototype);//false。所以调用的并不是自己写的call函数,而是函数原型上的call函数。
得知这一点,说明了__proto__的指向是在new实例创建空间之后到隐藏的return行为(不是自己写的return)之前更改的。
所以打算该__proto__试试,发现之前写的this.fn.this 有误,fn已经是被返回的函数了,应该改成this.this。

let obj = {
    name: "OBJ"
};
let Fn = function(){
    fn = function(a,b){
        console.log(this);
        console.log(this.name);
        console.log(a,b);
    }
    fn.__proto__ = this.__proto__;
    return fn;
}

/*
* call 的要求 ,1、改变this指向一个实参;2、其余实参传入并执行。
*/
Fn.prototype.call = function(){
    let otherParams = [...arguments];//arguments是一个类数组。就算是一个数组,也尽量不要破坏arguments的原内容
    let param1 = otherParams.shift();
    // console.log(otherParams);
    // console.log(param1);
    //fn1.call时,this指向fn1。
    console.log(this);
    this.this = param1;//此时的f1是一个函数
    //this.fn().this = param1;//this.fn()代表的是函数执行的返回值,报错,返回undefined没有this属性。所以考虑用闭包。
    this(...otherParams);
}

let fn1 = new Fn();//{fn:xxxfff111} 现在new一个实例,其实被替代了。
// fn1.fn();
// console.log(fn1.name);
fn1.call(obj,12,13);
打印:
[object Function]
global {DTRACE_NET_SERVER_CONNECTION: , DTRACE_NET_STREAM_END: , DTRACE_HTTP_SERVER_REQUEST: , DTRACE_HTTP_SERVER_RESPONSE: , DTRACE_HTTP_CLIENT_REQUEST: ,}
undefined
12 13

结果和想象完全不同。根据网上资料,函数执行时this不能赋值,不然要call和apply干啥。。。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值