new的用处
new的作用是通过构造函数来创建一个实例对象,该实例与原型和构造函数之间的关系如下图所示:
具体步骤
javascript中的new是一个语法糖,new的过程如下
- 在内存中创建一个新对象
- 这个新对象内部的[[Prototype]]指针被赋值为构造函数的 prototype 属性
- 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)
很多直接把下面4.5的归为一步
- 执行构造函数内部的代码(给新对象添加属性)
- 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象
模拟 new 操作符
方案一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function _new(constructor, ...arg) { const obj = {}; obj.__proto__ = constructor.prototype; const result = constructor.apply(obj, arg); return typeof result === 'object' ? result : obj; } function Foo(name) { this.name = name; } var luckyStar = _new(Foo, 'luckyStar'); console,log(luckyStar.name);
|
方案二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function _new(fn, ...arg) { const obj = Object.create(fn.prototype); const newObj = fn.apply(obj, arg); return newObj instanceof Object } function GirlName(name, age) { this.name = name; this.age = age; this.sayName = function () { console.log(this.name); }; } const xiaoMei = _new(GirlName, 'Xiao Mei', 18) console.log(xiaoMei)
|
方案三
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
| function New() { let obj = {}; console.log(arguments); let constructor = [].shift.call(arguments); console.log(arguments); if (constructor.prototype !== null) { obj.__proto__ = constructor.prototype; } let ret = constructor.apply(obj, (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments))); console.log(arguments); console.log(typeof ret); if ((typeof ret === "object" || typeof ret === "function") && ret !== null) { return ret; } return obj; }
function name(a, b) { this.a = a; this.b = b; }
let c = New(name, 1, 2) let d = new name(1, 2) console.log(c); console.log(d);
|
为什么要判断返回值的类型?
这是因为new一个实例的时候,如果没有return,就会根据构造函数内部this绑定的值生成对象,如果有返回值,就会根据返回值生成对象,为了模拟这一效果,就需要判断apply后是否有返回值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function GirlName(name, age) { this.name = name; this.age = age; this.sayName = function () { console.log(this.name); };
return { name: 'Tomboy', age: 30, sayName: function() { console.log(this.name) } } }
|
1 2
| let xiaoMei = new GirlName('Xiao Mei', 18); xiaoMei.sayName();
|