构造函数模式

/**
 * 构造函数模式
 * 1、与工厂模式相比
 *    a、没有显示的创建对象
 *    b、直接将属性和方法赋给了构造函数的 this 对象
 *    c、没有 return 语句
 * 
 * 2、直接调用构造函数时,构造函数与普通函数无异
 *    this 指向调用该函数的最后一个对象
 * 
 * 3、构造函数的缺点
 *    每个方法都要在每个实例上重新创建一遍,即每个实例的同名方法都不同一个方法
 *    即 c1.speak != c2.speak
 */

function Constructor (name, sex, job) {
  this.name = name
  this.sex = sex
  this.job = job
  // this.speak => new Function('console.log("hello...")')
  this.speak = function () {
    console.log('hello...')
  }
}

/**
 * 1、创建构造函数对象必须使用 new 操作符,new 操作符的四个步骤为
 *    a、创建一个新的对象
 *    b、将构造函数的作用域赋给新对象(因此 this 就指向了新对象)
 *    c、执行构造函数中的代码(为这个新对象添加属性)
 *    d、返回新对象
 * 
 * 2、生成的实例对象都有一个 constructor(构造函数) 属性,该属性指向构造函数
 *    生成的实例对象即是构造函数 Constructor 的实例,也是构造函数 Object 的实例
 */
const c1 = new Constructor('tang', 'man', 'web design')
const c2 = new Constructor('chen', 'womam', 'teacher')
console.log(c1)
console.log(c2)

// true,实例对象是构造函数 Constructor 的实例
console.log(c1 instanceof Constructor)
// false,实例对象不是构造函数 Function 的实例
console.log(c1 instanceof Function)
// true,实例对象也是对象 Object 构造函数的实例(对象均继承自 Object)
console.log(c1 instanceof Object)

/**
 * 构造函数直接调用
 */
const o = new Object()
Constructor.call(o, 'chen', 'womam', 'teacher')
console.log(o)

/**
 * 每个同名方法在实例上都会被重新创建
 */
const c3 = new Constructor('tang', 'man', 'web design')
const c4 = new Constructor('chen', 'womam', 'teacher')
console.log(c3.speak == c4.speak) // false

/**
 * 对于缺点的改进方法,设置了一个全局的函数,但也有新的问题
 * 1、若对象需要定义多个方法,则需要创建多个全局函数,没有封装性可言
 */
function ConstructorMethod (name, sex, job) {
  this.name = name
  this.sex = sex
  this.job = job
  this.speak = speak // 相当于指向到了一个地址的指针
}

// 全局函数
function speak () {
  console.timeLog('hello...')
}

const m1 = new ConstructorMethod('tang', 'man', 'web design')
const m2 = new ConstructorMethod('chen', 'womam', 'teacher')

console.log(m1.speak === m2.speak) // true

你可能感兴趣的:(构造函数模式)