首发于CoffeeCodes
js-constructor

js-constructor

what

JavaScript语言使用构造函数(constructor)作为对象的模版。

所谓“构造函数”,就是专门用来生成实例对象的函数。它就是对象的模板,描述实例对象的基本结构。

constructor方法是类的默认方法,通过new命令生成对象实例,自动调用该方法。

一个类必须有constructor方法,如果没有显示定义,一个空的constructor方法会被默认添加。

// 定义了一个空的类Point,
class Point {
    // JavaScript引擎会自动为它添加一个空的constructor方法
}

// 等同于
class Point {
  constructor() {}
}

constructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象。

why

特点

  • 函数体内部使用了this关键字,代表了所要生成的对象实例。
  • 生成对象的时候,必须使用new命令。

类必须使用new调用,否则会报错。

这是它跟普通构造函数的一个主要区别,后者不用new也可以执行。

class Foo {
    constructor() {
        return Object.create(null);
    }
}

Foo()
// TypeError: Class constructor Foo cannot be invoked without 'new'

缺点

同一个构造函数的多个实例之间,无法共享属性,从而造成对系统资源的浪费。

function Cat(name, color) {
  this.name = name;
  this.color = color;
  this.meow = function () {
    console.log('喵喵');
  };
}

var cat1 = new Cat('大毛', '白色');
var cat2 = new Cat('二毛', '黑色');

cat1.meow === cat2.meow
// false

这个问题的解决方法,就是JavaScript的原型对象(prototype)。

how

constructor属性

  • 有了constructor属性,可以得知某个实例对象,到底是哪一个构造函数产生的。

如果不能确定constructor属性是什么函数,有一个办法,通过name属性,从实例得到构造函数的名称。

function Foo() {}
var f = new Foo();
console.log(f.constructor.name);    // Foo
  • 有了constructor属性,就可以从一个实例对象新建另一个实例。
function Constr() {}

// x是构造函数Constr的实例
var x = new Constr();

// 从x.constructor间接调用构造函数
var y = new x.constructor();

console.log(y instanceof Constr);   // true
  • constructor属性表示原型对象与构造函数之间的关联关系,如果修改了原型对象,一般会同时修改constructor属性,防止引用的时候出错。
function Person(name) {
  this.name = name;
}

Person.prototype.constructor === Person // true

Person.prototype = {
  method: function () {}
};

Person.prototype.constructor === Person // false
Person.prototype.constructor === Object // true

所以,修改原型对象时,一般要同时修改constructor属性的指向。

// 坏的写法
C.prototype = {
  method1: function (...) { ... },
  // ...
};

// 好的写法
C.prototype = {
  constructor: C,
  method1: function (...) { ... },
  // ...
};

// 更好的写法
C.prototype.method1 = function (...) { ... };

发布于 2019-12-06 12:01