例:我们需要得到一组不同边长的正方形,并计算他的面积和周长
最初我们可能会写出这样的代码
这些代码可以解决问题,但是它的缺陷在于每一次调用getArea()、getLength()函数时,都会开辟新的内存空间,因为边长的不同,函数都各不相同,但是其实他们是同一形式的,这样未免太过于浪费内存。

  1. let squareList = [];
  2. let widthList = [5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6];
  3. for (let i = 0; i < 12; i++) {
  4. squareList[i] = {
  5. width: widthList[i],
  6. getArea() {
  7. return this.width * this.width;//每一次的调用都是不一样的
  8. },
  9. getLength() {
  10. return this.width * 4;
  11. },
  12. };
  13. }

学会声明函数和原型进行对象的(批量)创建

为了将同一形式的函数进行集成,使每一次调用都不必开辟新的内存空间,可以使用函数和原型,并通过函数的原型是代码更加整体化

function createSquare(width) {//其实就是构造函数
   let obj = Object.create(createSquare.squarePrototype);
   obj.width = width;
   return obj;
   }
   createSquare.squarePrototype = {//其实不必使用函数的原型(使用其他的名字也可以,如common)这样使
     getArea() {                   //代码更加集成,整体化,但是new操作符设定是构造函数的prototype
     return this.width * this.width;
     },
     getLength() {
     return this.width * 4;
     },
     constructor: createSquare,//用来原型所属的构造器
     };
     let square = createSquare(5);

new命令的作用

在使用new命令配合构造函数进行对象创建时,new操作符会自动进行以下工作
以new X( )为例

  1. new命令会自动创建一个空对象
  2. new命令会将这个空对象与其构造函数的原型相联系,为X.prototype(使得我们写完对象的原型后不必再使用Object.create()方法,以及constructor的设置)
  3. new命令会将this关键字指向空对象
  4. new命令执行构造函数中的代码并会返回创建的对象(如果构造函数中有return语句,且return了一个对象,new命令就会返回这个对象,否则就会返回生成的对象)
  5. 如果构造函数中没有this关键字,new命令会返回一个空对象
  6. new.target 函数内部可以使用new.target属性,来判断函数是否是new命令调用,使用new命令时,返回的是当前函数,否则返回undefined

因此我们需要的工作就是为X()构造函数添加属性以及设置对象的原型来保存共用属性。因此上例就变成了

  function Square(width) {
        this.width = width;
      }
      Square.prototype.getArea = function () {//通过原型的设置保存共用属性
        return this.width * this.width;
      };
      Square.prototype.getLength = function () {
        return this.width * 4;
      };
      let square = new Square(5);