手写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; //判断返回值
}
相关推荐
Ivanqhz17 小时前
LLVM IR 转 SMT公式
java·开发语言
小红的布丁17 小时前
Reactor 模型详解:单 Reactor、主从 Reactor 与 Netty 思想
android·java·开发语言
北城笑笑17 小时前
FPGA 与 市场主流芯片分类详解:SoC/CPU/GPU/DPU 等芯片核心特性与工程应用
前端·单片机·fpga开发·fpga
被摘下的星星17 小时前
Java的类加载
java·开发语言
skilllite作者17 小时前
SkillLite 多入口架构实战:CLI / Python SDK / MCP / Desktop / Swarm 一页理清
开发语言·人工智能·python·安全·架构·rust·agentskills
秋月的私语17 小时前
遥感影像拼接线优化工具:基于Qt+GDAL+OpenCV的从零到一实践
开发语言·qt·opencv
A923A17 小时前
【从零开始学 React | 第四章】useEffect和自定义Hook
前端·react.js·fetch·useeffect
xwz小王子17 小时前
智元发布 GO-2:动作空间推理 + 全生命周期闭环,让机器人稳定可靠落地
开发语言·golang·机器人
charlie11451419117 小时前
通用GUI编程技术——图形渲染实战(二十八)——图像格式与编解码:PNG/JPEG全掌握
开发语言·c++·windows·学习·图形渲染·win32
ZC跨境爬虫17 小时前
批量爬取小说章节并优化排版(附完整可运行脚本)
前端·爬虫·python·自动化