zlx362211854 / daily-study

每日一个知识点总结,以issue的形式体现
10 stars 6 forks source link

25. 模拟实现 new 运算符 #56

Open goldEli opened 5 years ago

goldEli commented 5 years ago

模拟实现 new 运算符

var Person = function(name) {
  this.name = name
}
Person.prototype.say = function (msg) {
    console.log(`${this.name} say: ${msg}`)
}
var lily = new Person('lily')
lily.say("hello world")
// => lily say: hello world

const simulateNew = function() {
  // some code
}

var lily = simulateNew(Person, 'lily')
lily.say("hello world")
// 预期输出应该是 lily say: hello world
goldEli commented 5 years ago

先来看看 new 做了什么, 来自 MDN 官方的定义:

  1. Creates a blank, plain JavaScript object;
  2. Links (sets the constructor of) this object to another object;
  3. Passes the newly created object from Step 1 as the this context;
  4. Returns this if the function doesn't return its own object.

总结来说,this 主要就干了四件事,1)创建一个新的实例对象,2)实例的 __propto__ 属性指向构造函数的原型,3)this 指向实例,4)如果构造函数没有返回,就返回实例。

具体实现:

const simulateNew = function(constructor, param) {
  // 1. 创建一个实例
  var o = {}
  // 2. __proto__ 指向构造函数的原型
  o.__proto__ = constructor.prototype
  // 3. this 指向实例
  var ret = constructor.call(o, param)
  // 4. 返回实例或者constructor返回的对象
  return ret || o
}

var lily = simulateNew(Person, 'lily')
lily.say("hello world")
// => lily say: hello world
zlx362211854 commented 5 years ago
// 定义一个构造函数
var Person = function(name) {
  this.name = name;
}
// 定义构造函数的say方法
Person.prototype.say = function(msg) {
  console.log(this.name + ' say: ' + msg);
}
// 实现N方法
var N = function(Func) {
  return function() {
    // 定义一个用于返回的对象
    var obj = {};
    // 将构造函数的prototype赋值给obj对象的__proto__属性
    obj.__proto__ = Func.prototype;
    // 将构造函数的this重定向到obj对象中来
    Func.apply(obj, arguments);
    // 返回obj对象
    return obj
  }
}

var lily = N(Person)('lily');
console.log(lily.say('hello'))
// lily say: hello
roxy0724 commented 5 years ago
const simulateNew = function() {
  let obj = {}
  const constructor = [].shift.call(arguments)
  constructor.apply(obj, arguments)
  obj.__proto__ = constructor.prototype
  return obj
}