手写call,apply,bind,new

三种情况都是改变this的指向,不同的是bind返回的是一个函数

javascript 复制代码
//call
let foo = {
    value: 1
};

Function.prototype.call2 = function (context) {
    const context2 = context || window
    //this指的是要改变this函数
    context2.fn = this
    const args = [...arguments].slice(1)
    //调用一次再删除即可
    const result = context2.fn(...args)
    delete context2.fn
    return result
}

console.log(bar.call2(foo,'james',20));
javascript 复制代码
//apply
Function.prototype.apply2 = function (context,arr=[]) {
    const context2 = context || window
    context2.fn = this
    console.log(arr,888);
    const result = context2.fn(...arr)
    delete context2.fn
    return result
}

console.log(bar.apply2(foo,['james',20]));
javascript 复制代码
var value = 2;

var foo = {
    value: 1
};

function bar(name, age) {
    this.habit = 'shopping';
    console.log(this.value);
    console.log(name);
    console.log(age);
}

bar.prototype.friend = 'kevin';

var bindFoo = bar.bind(foo, 'daisy');

var obj = new bindFoo('18');
// undefined
// daisy
// 18
console.log(obj.habit);
console.log(obj.friend);
// shopping
// kevin


//bind
function bar3() {
    console.log(this.value);
}
Function.prototype.bind2 = function (context) {
    if(typeof this !== 'function'){
        throw new Error("this is not a function")
    }
    let _this = this //此处获取的是指向bar的this
    let args = [...arguments].slice(1)

    let fnop = function(){}
    //判断是否作为构造函数使用
    let fBound = function(){
        let bindArgs = [...arguments]
        //this为实例对象,在实例对象中的this指向无效 指向window
        return _this.apply(this instanceof fnop?this:context,[...args, ...bindArgs])
    }
    fnop.prototype = this.prototype
    //获取原型对象,继承原型对象的属性
    fBound.prototype = new fnop() //防止一同修改this的原型对象,使用fnop作为中间站
    return fBound
}

const bindFn = bar3.bind2(foo)
bindFn()

如果bind返回的参数 作为构造函数使用,那么这个this的指向就无效了。

javascript 复制代码
//new

function Person(){}
let person = objectFactory(Person,data)
function objectFactory(){
    let obj = new Object()
    const Constructor = [].shift.call(arguments) //会返回第一个参数,也就是构造函数
    const ret = Constructor.apply(obj,arguments) //绑定了this
    obj.__proto__ = Constructor.prototype
    return typeof ret === "object"?ret:obj; //判断返回值
}
相关推荐
CappuccinoRose2 分钟前
JavaScript 学习文档(二)
前端·javascript·学习·数据类型·运算符·箭头函数·变量声明
A9better2 分钟前
C++——不一样的I/O工具与名称空间
开发语言·c++·学习
清水白石0085 分钟前
《为什么说 deque 是 Python 滑动窗口的“隐藏神器”?深入解析双端队列的高效之道》
开发语言·python
杜子不疼.6 分钟前
Ascend_C自定义算子开发
c语言·开发语言
这儿有一堆花8 分钟前
Vue 是什么:一套为「真实业务」而生的前端框架
前端·vue.js·前端框架
WooaiJava21 分钟前
流式TTS音频播放项目 - 面试问答(后端)
java·开发语言
全栈前端老曹22 分钟前
【MongoDB】深入研究副本集与高可用性——Replica Set 架构、故障转移、读写分离
前端·javascript·数据库·mongodb·架构·nosql·副本集
新缸中之脑30 分钟前
开发AI代理必备的8个Python 库
开发语言·人工智能·python
暴走十八步33 分钟前
PHP+vscode开启调试debug
开发语言·vscode·php
郝学胜-神的一滴37 分钟前
Python 列表 vs 数组:深入解析与最佳选择指南
开发语言·python·程序人生