实现new、apply、call、bind底层逻辑

1.应用场景

new、apply、call、bind都作用在函数上并且会改变函数this的指向,通俗地讲是“借用其他人的方法”

b借用a的方法:

let a = {
    name:'wyy',
    getName:function(msg){
        return msg+this.name
    }
}
let b = {
    name:'cyt'
}
console.log(a.getName("hello~"));
console.log(a.getName.call(b,'hi~'));
console.log(a.getName.apply(b,['hi~']));
let say = a.getName.bind(b,'hi~')
console.log(say());

call和apply的区别在于参数的形式,apply是以数组的形式进行传参

fun.call(thisArg,p1,p2......)

fun.apply(thisArg,[p1, p2,.......])

fun.bind(thisArg,p1,p2.......)、

  • 判断数据类型
  • 类数组借用方法
  • 获取数组的最大值、最小值
  • 继承

2.手写实现

(1)new方法(只有function才此方法)

  • 创建一个新对象
  • 将构造函数作用域赋值给新对象(让构造函数的this指向这个新对象)
  • 执行构造函数(为新对象添加属性)
  • 返回新对象

new关键字执行之后总是会返回一个对象,要不是新对象,要不就是return语句指定的对象。

function _new(ctor, ...args){
    if(typeof ctor !== 'function'){
        throw 'ctor is must a function'
    }
    let obj = new Object()
    // 改变实例对象的指向,指向构造函数的原型链
    obj.__proto__ = Object.create(ctor.prototype)
    let res = ctor.apply(obj,...args)

    let isObject = typeof res === 'object'&&res !== null
    let isFunction = typeof res === 'function';
    // return返回的是新创建的实例对象或者是函数指定的return对象
    return isObject||isFunction ? res:obj
}

(2)call方法手写实现

Function.prototype.call = function(context,...args){
    var context = context || window;
    context.fn = this;
    // 直接执行函数,eval()输入参数是字符串
    var result = eval('context.fn(context.fn(...args))')
    delete context.fn
    return result
}

(3)apply方法手写实现(传的参数没有扩展符)

Function.prototype.apply = function(context,args){
    var context = context || window;
    context.fn = this;
    // 直接执行函数,eval()输入参数是字符串
    var result = eval('context.fn(context.fn(...args))')
    delete context.fn
    return result
}

(4)bind方法手写实现

// bind方法返回的是一个函数
Function.prototype.bind = function (context, ...args) {
    if (typeof this !== 'function') {
        throw new Error('this must be a function')
    }
    var self = this;
    var fbound = function () {
        self.apply(this instanceof self ? this : context,
            args.concat(Array.prototype.slice.call(arguments)))
    }
    if (this.prototype) {
        fbound.prototype = Object.create(this.prototype)
    }
    return fbound
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值