没有对象?new一个!

咱们都知道,使用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

  1. 建立一个函数,可返回一个新的对象
  2. 须要访问到Student构造函数里的属性
  3. 须要访问到Student.prototype中的属性和方法

具体步骤分析

1、参数传递

若要实现上面代码的相同效果,首先明确须要一个“类”的参数,以及其它参数(如name)。
js 的函数参数很是灵活,形参数量可不肯定(使用...args),也可不给出。函数中有一个 与生俱来的arguments对象,具备length属性,但不是数组,因此不可以使用数组方法。app

arguments 简单分析

下述代码中的输出语句结果即为所传实参的集合:函数

{ '0': [Function: Student], '1': '小明', '2': 18 }学习

function objectFactory() {
    console.log(arguments);
}
const person = objectFactory(Student, '小明',18);

2、方法实现

1.获得 Student 类的构造函数

由前面 arguments 简单分析可知,arguments中的第一个参数即为Student的构造函数。上面说到,arguments 并不是数组,那咱们如何获得第一项呢?this

两种方法:[].shift.call(arguments)Array.from(arguments)prototype

var Constructor = [].shift.call(arguments);

2.建立一个新的对象

建立一个新的对象很是简单,以下:code

const obj = new Object();

3.设置新对象的 __proto__ 属性

__proto__是对象的私有属性,指向构造该对象的构造函数的原型。因此此步须将新的对象的此属性指向 Constructor的原型。对象

obj.__proto__ = Constructor.prototype;

4.获得构造函数上的 this 属性

若要实例化一个“类”,则必须调用其构造函数,在执行构造函数时,其 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的学习,原型的概念更清晰了,在具体的实现过程当中也学习到了shiftcallapply等方法的一些使用。收获颇丰。

相关文章
相关标签/搜索