手写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; //判断返回值
}
相关推荐
NMBG227 分钟前
[JAVAEE] 面试题(四) - 多线程下使用ArrayList涉及到的线程安全问题及解决
java·开发语言·面试·java-ee·intellij-idea
Py小趴13 分钟前
Python自学之Colormaps指南
开发语言·python·数据可视化
晒足以百八十18 分钟前
基于Python 和 pyecharts 制作招聘数据可视化分析大屏
开发语言·python·信息可视化
浮华似水23 分钟前
Javascirpt时区——脱坑指南
前端
王二端茶倒水26 分钟前
大龄程序员兼职跑外卖第五周之亲身感悟
前端·后端·程序员
_oP_i31 分钟前
Web 与 Unity 之间的交互
前端·unity·交互
钢铁小狗侠33 分钟前
前端(1)——快速入门HTML
前端·html
敲代码不忘补水38 分钟前
生成式GPT商品推荐:精准满足用户需求
开发语言·python·gpt·产品运营·产品经理
凹凸曼打不赢小怪兽1 小时前
react 受控组件和非受控组件
前端·javascript·react.js
清风fu杨柳1 小时前
centos7 arm版本编译qt5.6.3详细说明
开发语言·arm开发·qt