手写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; //判断返回值
}
相关推荐
DEMO派4 小时前
首页图片懒加载实现方案解析
前端
资生算法程序员_畅想家_剑魔4 小时前
Java常见技术分享-13-多线程安全-锁机制-底层核心实现机制
java·开发语言
用户952081611794 小时前
百度地图MapVThree Editor:地图编辑
前端
shix .4 小时前
spiderdemo 2-混淆
开发语言·python
lsx2024064 小时前
Bootstrap 页面标题:设计指南与最佳实践
开发语言
黎雁·泠崖4 小时前
C 语言结构体全解析:声明 + 内存对齐 + 位段 + 传参优化
c语言·开发语言
世转神风-4 小时前
qt-文件自动按编号命名
开发语言·qt
lkbhua莱克瓦244 小时前
基础-MySQL概述
java·开发语言·数据库·笔记·mysql
程序员龙语4 小时前
CSS 文本样式与阴影属性
前端·css
龘龍龙4 小时前
Python基础学习(七)
开发语言·python·学习