原型链继承-Prototype chain

Child.prototype = new Parent();

借助原型链实现继承, 引起引用类型的原型属性会被所有实例共享

function Parent2() {
	this.name = 'parent2';
}

Parent2.prototype.say = function() {
	alert(this.name);
}

function Child2() {
	this.type = 'child2';
}

Child2.prototype = new Parent2();  // 缺点是父类构造函数执行两次

console.log(new Child2().say())

借助构造函数继承-constructed function

借助构造函数实现继承,子类不能继承父类prototype上的方法


function Parent1() {
	this.name = 'parent1';
}
Parent1.prototype.say = function() {
	alert(this.name);
}

function Child1() {
	this.type = 'child1';
	Parent1.call(this);
}

console.log(new Child1());

组合继承-combination

function Parent3() {
	this.name = 'parent3';
	this.play = [1, 2, 3];
}

Parent3.prototype.say = function() {
	alert(this.name);
}

function Child3() {
	this.type = 'child3';
	Parent3.call(this);
}

Child3.prototype = new Parent3();

var s3 = new Child3();
var s4 = new Child3();

s3.play.push(4);

console.log(s3.play, s4.play) // [1, 2, 3, 4],  [1, 2, 3];

共享原型-Shared-prototype

组合继承优化-1

Child.prototype = Parent.prototype

// 组合继承,优化1
function Parent4() {
	this.name = 'parent4';
	this.play = [1, 2, 3];
}

Parent4.prototype.say = function() {
	alert(this.name);
}

function Child4() {
	this.type = 'child4';
	Parent4.call(this);
}

Child4.prototype = Parent4.prototype;  // 缺点是,子类指向的构造函数与父类是一个
// Child4.prototype.constructor = Parent4;  // 这样无法区分父类的原型对象了

var s5 = new Child4();
var s6 = new Child4();

console.log(s5, s6);

console.log(s5 instanceof Child4,s5 instanceof Parent4);  // true, true
console.log(s5.constructor)  // Parent4

Object.create

组合继承优化-2

Child.prototype = Object.create(Parent.prototype)

function Parent5() {
	this.name = 'parent5';
	this.play = [1, 2, 3];
}

function Child5() {
	this.type = 'child5';
	Parent5.call(this);
}

Child5.prototype = Object.create(Parent5.prototype);
Child5.prototype.constructor = Child5;

var s7 = new Child5();

console.log(s7 instanceof Child5, s7 instanceof Parent5); // true, true
console.log(s7.constructor);  // Child5

你不知道的javascript之Object.create 和new区别

Object.create方法及其在继承上的应用

使用 class 关键字

class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

class Square extends Polygon {
  constructor(sideLength) {
    super(sideLength, sideLength);
  }
  get area() {
    return this.height * this.width;
  }
  set sideLength(newLength) {
    this.height = newLength;
    this.width = newLength;
  }
}

var square = new Square(2);

写一个贴近实际开发原型链继承的例子-demo

写一个封装DOM查询的例子

function Elem(id) {
	this.elem = document.getElementById(id);
}
Elem.prototype.html = function(val) {
  var elem = this.elem;
  if (val) {
  	elem.innerHTML = val;
  	console.log(this)
  	return this; // 链式操作
  } else {
  	return elem.innerHTML;
  }
}
Elem.prototype.on = function(type, fn) {
	var elem = this.elem;
	if(elem.addEventListener) {
		elem.addEventListener('type', fn, false);
	} else if(elem.attachEvent) {
		elem.attachEvent('on' + type, fn);
	} else {
		elem['on' + type] = fn;
	}
    return this;
}

var div1 = new Elem('div1');
div1.html('');
div1.on('click', alert('click')).html('youyi');

更多-more

mozilla.org/Inheritance_and_the_prototype_chain