JavaScript是基于原型(prototype), 沒(méi)有python中class 的概念氮昧。
var Cartoon={
name:'Micky Mouse',
height:15,
run:function () {
console.log(this.name+'is quacking')
}
};
function createCartoon(name) {
var p = Object.create(Cartoon);
p.name=name;
return p
}
var p2 = createCartoon('Donald Duck');
console.log(p2.name); //'Donald Duck'
p2.run() //'Donald Duck is running'
構(gòu)造函數(shù)
在JavaScript中所踊,可以用關(guān)鍵字new來(lái)調(diào)用這個(gè)函數(shù),并返回一個(gè)對(duì)象:
function Cat(name) {
this.name = name;
this.hello=function () {
console.log('hello'+this.name)
}
}
var k1 = new Cat('kitty'); // new 別忘了寫
k1.hello();
同上
function Cat(name) { // 構(gòu)造函數(shù)首字母要大寫
this.name=name
}
Cat.prototype.hello=function () {
console.log('hello'+this.name)
};
var k1 = new Cat('kitty');
k1.hello()
用Cat()創(chuàng)建的對(duì)象還從原型上獲得了一個(gè)constructor屬性沙咏,它指向函數(shù)Cat本身:
console.log(k1.constructor===Cat.prototype.constructor) //true
不寫new時(shí):
function Robot(props) {
this.name = props.name || 'John Doe';
this.inventor = props.inventor || 'None'
}
Robot.prototype.sayHi = function () {
console.log('hello,hello hello'+this.name + 'my inventor is '+ this.inventor)
};
function createNewRobot(props) {
return new Robot(props || {}) // 在這里封裝new的相關(guān)操作
}
傳參時(shí):
var r1 = createNewRobot({
name:'David',
inventor:'Alice'
});
r1.sayHi()
動(dòng)態(tài)原型創(chuàng)建對(duì)象
function Factory(name,location) {
this.name = name;
this.location = location;
if (typeof this.recruit !== 'function'){ // 判斷this.recruit這個(gè)屬性是不是function食茎,如果不是function則證明是第一次創(chuàng)建對(duì)象
Factory.prototype.recruit = function () {
console.log(this.name+'starting'+ ' in ' + this.location )
};
}
}
let f1 = new Factory('NNL','Jilin');
console.log(f1.name,f1.location);
f1.recruit()
原型和原型鏈
proto 和 prototype
prototype是函數(shù)才有的屬性
proto是每個(gè)對(duì)象都有的屬性
在大多數(shù)情況下, proto可以理解成構(gòu)造器原型丹锹, 即:
__proto__ === constructor.prototype
var a = {};
console.log(a.prototype); //undefined
console.log(a.__proto__); //Object {}
var b = function(){}
console.log(b.prototype); //b {}
console.log(b.__proto__); //function() {}
由于proto是任何對(duì)象都具有的屬性稀颁,同python一樣,JS中也是萬(wàn)物皆對(duì)象楣黍,所以會(huì)形成一條proto連接起來(lái)的鏈條匾灶,遞歸訪問(wèn)最終到頭,返回值是null租漂。
當(dāng)JS引擎查找對(duì)象的屬性時(shí)阶女,會(huì)先查找對(duì)象本身是否具有該屬性,如果不存在哩治,會(huì)在原型鏈上查找秃踩。
JS實(shí)現(xiàn)繼承的幾種方式
先定義一個(gè)父類
// 定義一個(gè)動(dòng)物類
function Animal (name) {
// 屬性
this.name = name || 'Animal';
// 實(shí)例方法
this.sleep = function(){
console.log(this.name + ' is sleeping now');
}
}
// 原型方法
Animal.prototype.eat = function(food) {
console.log(this.name + ' is having ' + food);
};
1、原型鏈繼承(核心:將父類的實(shí)例作為子類的原型)
function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true
這種方法缺點(diǎn)太多业筏,例如憔杨,創(chuàng)建子類實(shí)例時(shí),無(wú)法向父類構(gòu)造函數(shù)傳參蒜胖,無(wú)法實(shí)現(xiàn)多繼承等消别,不推薦。
2台谢、構(gòu)造函數(shù)繼承(使用父類的構(gòu)造函數(shù)來(lái)增強(qiáng)子類實(shí)例寻狂,等于是復(fù)制父類的實(shí)例屬性給子類)
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
只能繼承父類的實(shí)例屬性和方法,不能繼承原型屬性/方法, 不推薦朋沮。
3蛇券、實(shí)例繼承(為父類實(shí)例添加新特性,作為子類實(shí)例返回)
function Cat(name){
var instance = new Animal();
instance.name = name || 'Tom';
return instance;
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // false
不支持多繼承,不推薦纠亚。
4塘慕、拷貝繼承
function Cat(name){
var animal = new Animal();
for(var p in animal){
Cat.prototype[p] = animal[p];
}
Cat.prototype.name = name || 'Tom';
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
無(wú)法獲取父類不可枚舉的方法(不可枚舉方法,不能使用for in 訪問(wèn)到)不推薦菜枷。