手写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; //判断返回值
}
相关推荐
Tkto9 小时前
我用 WebGL 从「画个点」一路画到「贪吃蛇」
前端
xiaobaoyu9 小时前
前端代码常用规范
前端
吃好睡好便好9 小时前
MATLAB中图像的读取、写入和显示
开发语言·图像处理·学习·计算机视觉·matlab
xiaobaoyu9 小时前
img,word,excel,pdf文件在线预览
前端
lichenyang4539 小时前
从 H5 到 HarmonyOS:我做了一个 npm + OHPM 双端发布的 ArkWeb JSBridge 框架
前端
用户84298142418109 小时前
AI时代,JS混淆加密还有用吗?
前端·javascript
xiaobaoyu9 小时前
如何理解前端项目中的绝对路径和相对路径
前端
xiaobaoyu9 小时前
vue3+vite+vant4项目实战总结
前端
yaoxin5211239 小时前
476. Java 反射 - 调用方法
java·开发语言
咖啡星人k10 小时前
【无标题】
前端·ai·github