由于本文涉及到原型原型链、this指向等知识,如果不太清楚这方面的知识可以下:原型原型链可看下我写的另一篇文章:
轻松理解JS原型原型链,this指向推荐大家看下这篇文章**:**this、apply、call、bind
一:new 的实现原理
-
创建一个空对象
-
实例的__proto__ 和原型对象指向同一个地方(不理解可以看下轻松理解JS原型原型链)
-
执行构造函数方法,改变了Person中的this指向(不理解可以看下this、apply、call、bind),属性和方法被添加到obj引用的对象中
-
执行构造函数返回结果result,如果result是基本数据类型(数字、字符串、布尔类型等和null)会忽略返回值,返回obj(此时的person01就是这个obj); 如果result的是对象,则返回result
二:模拟实现
function Person(name, age){
this.name = name;
this.age = age;
}
var person01 = new Person("Monica","Galen")
// new做了以下隐式操作
new Person{
// 步骤1:创建了一个空对象
var obj = {};
// 步骤2...
obj.__proto__ = Person.prototype;
// 步骤3...
var result = Person.apply(obj,"Monica","Galen");
// 步骤4...
return (typeof result === 'object' && result) || obj
}
三: 源码实现
如果new是一个方法而不是一个运算符,它可能会这样执行
// 在 Function的原型对象上添加了一个method方法
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
// 由于 Function.__proto__ = Function.prototype, Function上有了method方法
// 执行了method方法后,Function的 prototype上有了new方法
Function.method("new", function () {
// 步骤1:创建一个新对象,步骤2:它继承自构造函数的原型对象
var that = Object.create(this.prototype);
// 步骤3:调用构造函数,绑定this到新对象上
var other = this.apply(that, arguments);
// 步骤4:如果它的返回值不是对象,就返回该that对象
return (typeof other === "object" && other) || that;
});
function Person(name) {
this.name = name;
}
// 由于 Person.__proto__ = Function.prototype,所以Person有了new方法
let person01 = Person.new("Ross");
console.log(person01);
// 此时我们打印 person01;可以看看 person01是什么;并且
person01.__proto__ === Person.prototype; // true
// 我们在用原来的方式创建person02
let person02 = new Person("Chandler");
console.log(person02);
// 发现了吗?Object.create其实就是利用空对象实现原型链继承
// Object.create 源码实现
// Object.create = function(o){
// function F();
// F.prototype = o;
// return new F();
// }