new的模拟实现

转自:https://www.cnblogs.com/jztan/p/12397423.html

new

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象类型之一

function Animal(name) {
     
  this.name = name;
}
Animal.prototype.sayName = function() {
     
  console.log("I'm " + this.name);
}
var cat = new Animal('Tom');
console.log(cat.name); // Tom
console.log(cat.__proto__ === Animal.prototype); // true
cat.sayName(); // I'm Tom

从上面的例子可以得出两点结论:

  • new操作符实例化了一个对象;
  • 这个对象可以访问构造函数的属性;
  • 这个对象可以访问构造函数原型上的属性;
  • 对象的 proto 属性指向了构造函数的原型;

因为 new 的结果是一个新对象,所以在模拟实现的时候,我们也要建立一个新对象。
因为新对象里会具有构造函数里的属性,可以使用apply(obj, arguments)来给 obj 添加新的属性。

// construct: 构造函数
function newFunction() {
     
 var res = {
     };
 // 排除第一个构造函数参数
 var construct = Array.prototype.shift.call(arguments);
 res.__proto__ = construct.prototype;
 // 使用apply执行构造函数,将构造函数的属性挂载在res上面
 construct.apply(res, arguments);
 return res;
}

测试如下:

function newFunction() {
     
 var res = {
     };
 var construct = Array.prototype.shift.call(arguments);
 res.__proto__ = construct.prototype;
 construct.apply(res, arguments);
 return res;
}
function Animal(name) {
     
  this.name = name;
}
Animal.prototype.sayName = function() {
     
  console.log("I'm " + this.name);
}
var cat = newFunction(Animal, 'Tom');
console.log(cat.name); // Tom
console.log(cat.__proto__ === Animal.prototype); // true
cat.sayName(); // I'm Tom

如果构造函数返回了一个对象,实例 cat中只能访问返回的对象中的属性:

function Animal(name) {
     
  this.name = name;
  return {
     
    prop: 'test'
  };
}
var cat = new Animal('Tom');
console.log(cat.prop); // test
console.log(cat.name); // undefined
console.log(cat.__proto__ === Object.prototype); // true
console.log(cat.__proto__ === Animal.prototype); // false

所以我们还需要判断返回的值是不是一个对象,如果是一个对象,我们就返回这个对象,如果没有,我们该返回什么就返回什么。
最终版:

// construct: 构造函数
function newFunction() {
     
 var res = {
     };
 // 排除第一个构造函数参数
 var construct = Array.prototype.shift.call(arguments);
 res.__proto__ = construct.prototype;
 // 使用apply执行构造函数,将构造函数的属性挂载在res上面
 var conRes = construct.apply(res, arguments);
 // 判断返回类型
 return conRes instanceof Object ? conRes : res;
}

结果:

function Animal(name) {
     
  this.name = name;
 return {
     
  prop: 'test'
  };
}
var cat = newFunction(Animal, 'Tom');
console.log(cat.prop); // test
console.log(cat.name); // undefined
console.log(cat.__proto__ === Object.prototype); // true
console.log(cat.__proto__ === Animal.prototype); // false

new操作符会干下面这些事:

  • 创建一个空的简单JavaScript对象(即{});
  • 链接该对象(即设置该对象的构造函数)到另一个对象 ;
  • 将步骤1新创建的对象作为this的上下文;
  • 如果该函数没有返回对象,则返回this。

你可能感兴趣的:(javascript,javascript,js)