day110-手写原生call()

前言

call()反正我是用的比较少吧,但是从大家的使用量来说,这个函数是非常的重要。因为他有一些方法,起了很重要的作用。比如简单的继承,指定上下文等。 用法 - MDN



function Product(name, price) {
this.name = name
this.price = price + '++'
}

function Food(name, price) {
// 下面的this表示Product在执行时真正的this值(严格模式。非严格模式则是指向全局对象)
Product.call(this, name, price)
this.category = 'food'
}
console.log(new Food('cheese', 5).name)

代码-call()

实现fun.protytype.myCall思路ES3 :

步骤一确定参数数量

  • 先实现确定参数数量的myCall,因为function.prototype.call(thisArg, arg1, arg2, …),实际上是不确定参数的
  • fun的参数全部存到fun的临时处fun.temp
  • fun.temp() 输出在fun中存有的参数
  • 删除fun中新增的temp,用delete

其他实现的思路好像都差不多。

Function.prototype.myCall = function (args) {
args.temp = this
args.temp()
delete args.temp
}

步骤二不确定参数数量

实现fun.protytype.myCall思路ES3 :

  • 对call的参数进行处理,用slice来分开参数
  • 对分开之后的参数做不同处理
  • 注意:非严格模式下thisArgs的null\undefined指向全局变量(浏览器是window)
  • 用eval来连接args
    Function.prototype.myCall = function (args) {
    // null错误处理
    args = args || window
    args.temp = this

    var result
    if (!args) {
    result = args.temp()
    } else {
    var argsList = []
    // 第二个参数及其以后的都存入数组, 注意arguments
    for (var i = 1, l = arguments.length; i < l; i++) {
    argsList.push('arguments[' + i + ']')
    }
    // todo: eval不是很推荐的方法,需要一个好的方式连接 eval() https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval
    result = eval('args.temp(' + argsList + ')')
    }
    delete fn.temp
    return result
    }

// 待测试

代码-apply()

apply()和call()差不多,就是差在apply传入数组参数。

Function.prototype.myApply() = function (thisArg, argsArr) {
// 注意Object()
thisArg = Object(thisArg) || window
thisArg.temp = this
var result
if (!argsArr) {
result = thisArg.temp
} else {
// 注意i = 0
var arrTemp = []
for (var i = 0, l = argsArr.length; i < l; i++) {
arrTemp.push('argsArr[' + i + ']')
}
result = eval('thisArg.temp(' + arrTemp + ')')
}
return result

参考

JavaScript深入之call和apply的模拟实现
能否模拟实现JS的call和apply方法
不能使用call,apply,bind,如何用js实现call或者apply的功能?

文章作者: lmislm
文章链接: http://lmislm.com/2019/05/02/2019-05-02/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LMISLMのBlog