Skip to content
On this page

关于 new 操作符

js
function realnew () {
  let obj = {}
  let Con = Array.prototype.shift.call(arguments)
  console.log(Con)
  obj.__proto__ = Con.prototype
  // 绑定this
  Con.apply(obj, arguments)
  return obj
}
let zhangsan = realnew(Person, 'zhangsan', 19)
zhangsan.say()

bind,call,apply 的区别

bind:obj.function.bind(obj) 将函数中的 this 指向 obj

js
Function.prototype.MyBind = function (context) {
  if (typeof this !== 'function') {
    throw TypeError('函数调用错误')
  }
  //获取参数
  const args = [...arguments].slice(1)
  fn = this
  return fn.apply(
    this instanceof Fn ? new fn(...arguments) : context,
    args.concat(...arguments)
  )
}
let obj = {
  name: 'z',
  say: function () {
    console.log(this)
  }
}
let obj2 = {
  name: '2222'
}
this.fn = obj.say.bind(obj2)
this.fn() // 模拟react 中的bind
// 三者都可以改变函数的this对象指向

apply:接收一个数组 第一个参数为 null 或者 undefined 默认指向 window

call: 同样第一个参数为 this 的指向 临时改变 this 指向一次

js
Function.prototype.mycall = function (context) {
// 获取传送进来的对象 context
var context = context || window
// 为 context 定义一个属性 fn 方法,赋值为 this,改变 this 指向,当前 this 指向
context.fn = this
// 定义一个数组,获取传递进来的参数
var args = []
for (var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']')
// 重点:这块使用字符串拼接后并 push 进数组,
// 当前 args = ['arguments[0]','arguments[1]']
// 因为如果直接 push 进数组,则 args = ['jxd',18],上下文未定义会报错
}
// 因此这儿使用 eval 函数来执行,因为当执行函数作为函数参数的时候
// eval 会调用 toString()方法,将['arguments[0]','arguments[1]']转为
// 'arguments[0]','arguments[1]'
eval('context.fn(' + args +')
// 执行完后删除 fn 属性,保持函数的清洁
delete context.fn

}
var foo = {
value:1
}
function bar(name,age) {
console.log(name + '今年' + age)
}
// 调用
bar.call2(foo,'jxd',18)

    三者的区别是apply接受一个数组,而call接受一个参数列表
    bind是永久改变this的指向 bind可以多次传入

    bind的实现

三者第一个参数都是 this 要指向的对象,如果如果没有这个参数或参数为 undefined 或 null,则默认指向全局 window 三者都可以传参,但是 apply 是数组,而 call 是参数列表,且 apply 和 call 是一次性传入参数,而 bind 可以分为多次传入 bind 是返回绑定 this 之后的函数,apply、call 则是立即执行