Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2021/01/29 - 模拟实现call、apply #37

Open
lxinr opened this issue Jan 29, 2021 · 0 comments
Open

2021/01/29 - 模拟实现call、apply #37

lxinr opened this issue Jan 29, 2021 · 0 comments

Comments

@lxinr
Copy link
Owner

lxinr commented Jan 29, 2021

Function.prototype.call()

call() 方法使用一个指定的this值和单独给出的一个或多个参数来调用一个函数,如果这个函数处于非严格模式下,this指定为nullundefined时会自动替换为指向全局对象,原始值会被包装

Function.prototype.myCall = function(context) {
  // `this`指定为`null`或`undefined`时会自动替换为指向全局对象即window
  // 当值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象
  if(typeof context === 'object') {
    if(context === null) context = window
  } else {
    if(context === undefined) context = window
    else context = Object(context)
  }

  context.fn = this // 将函数设为对象context的属性
  // 因为可以传参,且参数不定,因此需要遍历
  var args = []
  // i从1开始是因为第一个参数是this,所以需要忽略
  for(var i = 1, len = arguments.length; i < len; i++) {
    args.push('arguments[' + i + ']') // 字符串拼接,即类似于es6语法的 `arguments[${i}]`
  }
  // eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码
  // 在eval中,args自动调用 args.toString()方法,因此最终的效果相当于
  // var result = context.fn(arguments[1], arguments[2], ...)
  var result = eval('context.fn(' + args +')') // 执行函数

  delete context.fn; // 删除函数
  return result // 返回结果
}

Function.prototype.apply()

与call类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组

Function.prototype.myApply = function(context, argsArray) {
  // `this`指定为`null`或`undefined`时会自动替换为指向全局对象即window
  // 当值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象
  if(typeof context === 'object') {
    if(context === null) context = window
  } else {
    if(context === undefined) context = window
    else context = Object(context)
  }
  
  context.fn = this // 将函数设为对象context的属性

  var result;
  // 如果没有传参,则直接执行
  if(!argsArray) result = context.fn()
  else {
    // 如果有传参,则需要遍历处理
    var args = []
    for(var i = 0, len = argsArray.length; i < len; i++) {
      args.push('argsArray[' + i + ']') // 字符串拼接,即类似于es6语法的 `argsArray[${i}]`
    }
    // eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码
    // 在eval中,args自动调用 args.toString()方法,因此最终的效果相当于
    // var result = context.fn(argsArray[1], argsArray[2], ...)
    result = eval('context.fn(' + args +')') // 执行函数
  }

  delete context.fn; // 删除函数
  return result // 返回结果
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant