[js] 继承
原型链基本模式
所谓的 伪类
//不能使用对象字面量创建原型方法
//因为不能在子类内部调用超类函数,所以实践中很少会单独使用原型链
function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function() { return this.property; }; function SubType() { this.subproperty = false; } //inherit from SuperType SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function() { return this.subproperty; }; var instance = new SubType(); console.log(instance.getSuperValue()); //true console.log(instance instanceof Object); //true console.log(instance instanceof SuperType); //true console.log(instance instanceof SubType); //true console.log(Object.prototype.isPrototypeOf(instance)); //true console.log(SuperType.prototype.isPrototypeOf(instance)); //true console.log(SubType.prototype.isPrototypeOf(instance)); //true
#
var Mammal = function(name) { this.name = name; }; Mammal.prototype.get_name = function() { return this.name; }; Mammal.prototype.says = function() { return this.saying || ''; }; var myMammal = new Mammal('Herb the Mammal'); var name = myMammal.get_name(); // 'Herb the Mammal' console.log(name); var Cat = function(name) { this.name = name; this.saying = 'meow'; }; Cat.prototype = new Mammal(); Cat.prototype.purr = function(n) { var i, s = ''; for (i = 0; i < n; i += 1) { if (s) { s += '-'; } s += 'r'; } return s; }; //定义自己和父类同名的方法 Cat.prototype.get_name = function() { return this.says() + ' ' + this.name + ' ' + this.says(); }; var myCat = new Cat('Henrietta'); var says = myCat.says(); // 'meow' var purr = myCat.purr(5); // 'r-r-r-r-r' var name = myCat.get_name(); // 'meow Henrietta meow' console.log(myCat); console.log(says); console.log(purr); console.log(name); var name = myMammal.get_name(); // 'Herb the Mammal' console.log(name);
经典继承(借用构造函数)
//1
function SuperType() { this.colors = ["red", "blue", "green"]; } function SubType() { //inherit from SuperType SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push("black"); console.log(instance1.colors); //"red,blue,green,black" var instance2 = new SubType(); console.log(instance2.colors); //"red,blue,green"
//2
function SuperType(name) { this.name = name; } function SubType() { //inherit from SuperType passing in an argument SuperType.call(this, "Nicholas"); //instance property this.age = 29; } var instance = new SubType(); console.log(instance.name); //"Nicholas"; console.log(instance.age); //29
#注意子函数同名方法的问题
function Dog() { this.wow = function() { console.log('Wow'); } this.yelp = function() { this.wow(); } } function MadDog() { Dog.call(this); //只能用这种方法实现调用同名方法,但不改变父方法 this.yelp = function() { var self = this; setInterval(function() { self.wow(); }, 500); } } // 无效 // MadDog.prototype.yelp = function() { // var self = this; // setInterval(function() { // self.wow(); // }, 500); // } var Dog = new Dog(); Dog.yelp();
组合继承
function SuperType(name) { this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function() { console.log(this.name); }; function SubType(name, age) { SuperType.call(this, name); //继承属性 this.age = age; } SubType.prototype = new SuperType(); //继承方法 SubType.prototype.sayAge = function() { console.log(this.age); }; var instance1 = new SubType("Nicholas", 29); instance1.colors.push("black"); console.log(instance1.colors); //"red,blue,green,black" instance1.sayName(); //"Nicholas"; instance1.sayAge(); //29 var instance2 = new SubType("Greg", 27); console.log(instance2.colors); //"red,blue,green" instance2.sayName(); //"Greg"; instance2.sayAge(); //27
原型式继承
function object(o) { function F() {} F.prototype = o; return new F(); } var person = { name: "Nicholas", friends: ["Shelby", "Court", "Van"] }; var anotherPerson = object(person); anotherPerson.name = "Greg"; anotherPerson.friends.push("Rob"); var yetAnotherPerson = object(person); yetAnotherPerson.name = "Linda"; yetAnotherPerson.friends.push("Barbie"); console.log(person.friends); //"Shelby,Court,Van,Rob,Barbie"
原型式继承 ES5
//不能使用对象字面量创建原型方法
var person = { name: "Nicholas", friends: ["Shelby", "Court", "Van"] }; var anotherPerson = Object.create(person); anotherPerson.name = "Greg"; anotherPerson.friends.push("Rob"); var yetAnotherPerson = Object.create(person); yetAnotherPerson.name = "Linda"; yetAnotherPerson.friends.push("Barbie"); console.log(person.friends); //"Shelby,Court,Van,Rob,Barbie"
寄生组合式继承
function object(o) { function F() {} F.prototype = o; return new F(); } function inheritPrototype(subType, superType) { var prototype = object(superType.prototype); //create object prototype.constructor = subType; //augment object subType.prototype = prototype; //assign object } function SuperType(name) { this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function() { console.log(this.name); }; function SubType(name, age) { SuperType.call(this, name); this.age = age; } inheritPrototype(SubType, SuperType); SubType.prototype.sayAge = function() { console.log(this.age); }; var instance1 = new SubType("Nicholas", 29); instance1.colors.push("black"); console.log(instance1.colors); //"red,blue,green,black" instance1.sayName(); //"Nicholas"; instance1.sayAge(); //29 var instance2 = new SubType("Greg", 27); console.log(instance2.colors); //"red,blue,green" instance2.sayName(); //"Greg"; instance2.sayAge(); //27
#使用继承对一些方法的扩展使用
var a = Math.max.apply('', [3, 4, 5]); console.log(a); var aa = Math.min.apply('', [5, 3, 1]); console.log(aa); var b = Array.prototype.filter.call('123', function(a) { return a > 1; }) console.log(b); var c = [].filter.call('123', function(v) { return v > 1; }) console.log(c); //Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组 var e = Array.prototype.slice.call({ length: 2, 0: 'first', 1: 'second' }); // ["first", "second"] console.log(e); var f = Array.prototype.slice.call({ length: 2 }); // [undefined, undefined] console.log(f); var g = Array.prototype.slice.call({ 0: 'first', 1: 'second', 3: 'happy' }); // [] console.log(g);
Array.prototype.slice.call([1, 2, 3], 1, 2); // <- [2] String.prototype.split.apply('13.12.02', ['.']); // <- ['13', '12', '02'] var arr = [1, 2]; var add = Array.prototype.push.bind(arr, 3); add(); add(4); console.log(arr); // <- [1, 2, 3, 3, 4]