首先让我回忆一下创建对象的三种方法
- 单休模式
1 2 3 4 5 6 7 8 9 10 11
| const Person = { name: "angelee", sayname: function() { return this.name; } }
let ahui = Object.create(Person); ahui.name = "ahui" console.log(ahui.sayname())
|
- 构造函数
1 2 3 4 5 6 7 8 9
| const Person = function (name) { this.name = name; } Person.prototype.sayname = function () { return this.name; }
let ahui = new Person("ahui"); console.log(ahui.sayname());
|
- ES6 class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class Person { constructor (name) { this.name = name; } sayname () { return this.name; } }
let ahui = new Person('ahui'); console.log(ahui.sayname());
class Boy extends Person { constructor (name, age) { super(name) this.age = age } sayage() { return this.age } }
let angelee = new Boy('angelee', 18); console.log(angelee.sayname()); console.log(angelee.sayage());
|
我们发现, 创建对象的时候,除了单例是通过 Object.create()
创建对象,其它都是通过 new
操作实现的。
那new
到底做了什么呢 ?
让我们以下边这个为例详细分析一下
1 2 3 4 5
| const Person = function (name) { this.name = name; } const ahui = new Person('ahui') console.log(ahui.name);
|
让我们试一下其它方法实现 console.log(ahui.name)
也能正常输出 ahui
- 先创建一个空对象
1
| const ahui = new Object()
|
- 设置原型链,把 ahui 的
__proto__
成员指向 Person 函数对象的prototype
成员对象
1
| ahui.__proto__ = Person.prototype
|
- 把Person中的
this
指向ahui
1
| const result = Person.call(ahui)
|
- 将初始化完毕的新对象地址,保存到等号左边的变量中。判断Person的返回值类型,如果是值类型,返回obj。如果是引用类型,就返回这个引用类型的对象
自己实现一个 new 方法
第一种方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| const Person = function (name) { this.name = name; }
function myNew() {
var obj = new Object();
var Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
var ret = Constructor.apply(obj, arguments);
return typeof ret === 'object' ? ret : obj; }
const ahui = new Person('ahui'); console.log(ahui.name);
const angeli = myNew(Person, 'angeli') console.log(angeli);
angeli.name = 'angeli new' console.log(angeli.name);
|
第二种方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
function New(f) { return function () { console.log(arguments) var o = {"__proto__": f.prototype};
f.apply(o, arguments);
return o; } }
const Person = function (name) { this.name = name; }
const ahui = New(Person)('ahui') console.log(ahui.name)
|
自测一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function New(f) { return function () { let o = { "__proto__": f.prototype }
f.apply(o, arguments)
return typeof o === "object" ? o : f } }
const Person = function (name) { this.name = name }
Person.prototype.sayname = function() { return this.name }
const ahui = New(Person)('ahui') console.log(ahui.name) ahui.sayname()
|
关于 arguments
可以参考这篇文章: JS 函数实参转换为数组