咱们都知道,使用new
后可返回一个对象,一般用于实例化一个“类”。
用法:数组
function Student (name, age) { this.name = name; this.age = age; } Student.prototype.sayName = function() { console.log('I am '+ this.name); } const person =new Student('小明'); person.sayName(); // I am 小明
首先咱们分析一下,手动实现new须要什么。ruby
Student
构造函数里的属性Student.prototype
中的属性和方法若要实现上面代码的相同效果,首先明确须要一个“类”的参数,以及其它参数(如name
)。
js 的函数参数很是灵活,形参数量可不肯定(使用...args
),也可不给出。函数中有一个 与生俱来的arguments
对象,具备length
属性,但不是数组,因此不可以使用数组方法。app
arguments
简单分析下述代码中的输出语句结果即为所传实参的集合:函数
{ '0': [Function: Student], '1': '小明', '2': 18 }学习
function objectFactory() { console.log(arguments); } const person = objectFactory(Student, '小明',18);
Student
类的构造函数由前面 arguments
简单分析可知,arguments
中的第一个参数即为Student
的构造函数。上面说到,arguments 并不是数组,那咱们如何获得第一项呢?this
两种方法:[].shift.call(arguments)
或 Array.from(arguments)
prototype
var Constructor = [].shift.call(arguments);
建立一个新的对象很是简单,以下:code
const obj = new Object();
__proto__
属性__proto__
是对象的私有属性,指向构造该对象的构造函数的原型。因此此步须将新的对象的此属性指向 Constructor
的原型。对象
obj.__proto__ = Constructor.prototype;
若要实例化一个“类”,则必须调用其构造函数,在执行构造函数时,其 this
的值是动态的变化的,即为当前调用该函数的对象。get
但是这里有个问题,若此时直接调用构造函数并传值
Constructor(arguments);
最终结果将为undefined
。
这是为何呢?
缘由是构造函数中的 this
并无指向当前的新对象,此时apply()
方法就可完美解决这个问题(call()
方法也可),具体的apply()
的使用及apply()
与call()
的异同可参照大神文章。
结果:
function objectFactory(){ var Constructor = [].shift.call(arguments); var obj = new Object(); obj.__proto__ = Constructor.prototype; Constructor.apply(obj, arguments); return obj; } const person = objectFactory(Student, '小明', 18); person.sayName(); // I am 小明
对于手动实现new
的学习,原型的概念更清晰了,在具体的实现过程当中也学习到了shift
、call
、apply
等方法的一些使用。收获颇丰。