第一种写法:
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.lessons = ['Math','Physics']; } Person.prototype = { constructor: Person, getName: function(){ return this.name; } }
第二种写法:
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.lessons = ['Math','Physics']; Person.prototype.getName = function(){ return this.name; } }
第二种写法每次创建实例都会执行一遍对prototype的操作!关键是这个操作很没意义,这个方法对每个实例都是相同的。
第一种方法中, 当prototype在构造函数外面书写时,可以从形式上和内存分配中解决重复定义或分配内存的问题。
对应在内存中,第一种写法,无论你创建了多少实例,每个实例占据空间只是name, age,job和lessons。getName在内存中只有一份,所有实例共用; 第二种写法,每个新创建的实例会分配一块额外的空间(栈)来执行prototype的定义。
prototype在第一种方法中赋值的方式和第二种方法有何区别?
区别很大的,一个function类定义好,它默认的 constructor属性就是自己, 它的实例在访问constructor属性时会返回这个值。
function Person() {}; console.log(Person.prototype.constructor); // Person var p = new Person(); console.log(p.constructor); // Person 表示p的构造函数是Person类
方法1中为什么要定义constructor? 因为它给prototype重新赋值了,如果你不定义
constructor(Person.prototype = {getName: function() {}})
,那么上例中p.constructor返回值将是 Object, 即p的构造函数是Object,显然与事实不符。
方法1更明智的做法是不要重新给prototype赋值,只为prototype添加我们需要的属性getName, 改为
Person.prototype.getName = function() {return this.name;}
也就是第二种方法里的定义方法,这么写就不会覆盖prototype的默认属性。