JavaScript之原型和繼承
1、實現示例:
function Person(name, sex) { this.name = name; this.sex = sex; } Person.prototype = { name:'無名氏', sex:'未知', nation:'火星', getName: function() { return this.name; }, getSex: function() { return this.sex; }, getNation: function() { return this.nation; } } var people = new Person("Tom", "man"); alert(people.getName()); //使用構造物件時的name值 alert(people.getNation()); //使用原型中的nation值
我們把函式Person(也就是建立自定義物件的函式)稱為建構函式,Person.prototype稱之為Person的原型,可以看出JavaScript通過建構函式和原型的方式模擬實現了類的功能。prototype本質上是一個JavaScript物件,並且每個函式都有一個預設的prototype屬性。prototype原型中的屬性可以被原型所屬的類的自定義物件引用。
如果將People理解為父類,要定義一個子類Employee繼承父類原型中的屬性。那麼:
function Employee(employeeID,name,sex){ this.employeeID = employeeID; this.name = name; this.sex = sex; } Employee.prototype = new Person(); //將Employee的原型指向父類的物件 Employee.prototype.getEmployeeID = function() { return this.employeeID; }; //此時Employee的物件就可以呼叫Person中的方法 var boss = new Employee("001", "Jim", "man"); alert(boss.getEmployeeID()); //使用構造物件時的employeeID值 alert(boss.getName()); //使用構造物件時的name值 alert(boss.getNation()); //使用原型中的nation值
2、變數this:表示當前物件。如果在全域性作用域內使用this,則返回當前頁面物件window。如果在函式(方法)中使用this,則返回呼叫該函式的物件。可以使用call或apply重新指定this所代表的物件。
①在全域性作用域內:
<script type="text/javascript">
alert(this === window); // true
</script>
②在函式內:
var fruit = "apple"; //定義一個全域性變數,等價於window.fruit = "apple"; function test() { alert(this.fruit); } test(); //apple
③在方法內:
var obj = {
fruit: "orange",
test: function(){alert(this.fruit);}
};
obj.test(); // "orange"
3、物件的constructor屬性:始終指向建立該物件的建構函式。
var a = new Array(1, 56, 34, 12);
alert(a.constructor===Array); //true
var b = [1, 56, 34, 12];
alert(b.constructor===Array); //true
var c = new Function();
alert(c.constructor===Function); //true
var d = function(){};
alert(d.constructor===Function); //true
var Foo = function(){};
var obj = new Foo();
alert(obj.constructor.constructor === Function); //true
function Person(name) {
this.name = name;
}
var p = new Person("Tom");
alert(p.constructor===Person); //true
如果修改Person的prototype,Person建立的物件的constructor依然為Person
function Person(name) {
this.name = name;
}
//修改Person的原型,而不是全部覆蓋其原型
Person.prototype.getName = function() {
return this.name;
};
var p = new Person("Tom");
alert(p.constructor===Person); //true
但如果覆蓋掉Person的prototype,Person建立的物件的constructor則變為Object
function Person(name) {
this.name = name;
}
//覆蓋Person的原型
Person.prototype = {
getName: function(){
return this.name;
}
};
var p = new Person("Tom");
alert(p.constructor===Person); //false
alert(p.constructor===Object); //true
這是因為覆蓋Person的prototype時實際做的操作是:
Person.prototype = new Object({
getName: function(){
return this.name;
}
});
所以物件的constructor指向的是Object而非Person,可以用以下方法修正這個錯誤:
Person.prototype.constructor=Person;
特殊地:建構函式的原型的constructor也始終指向建構函式本身。
alert(String.prototype.constructor===String); //true
alert(Array.prototype.constructor===Array); //true
alert(Date.prototype.constructor===Date); //true
alert(Number.prototype.constructor===Number); //true
alert(Object.prototype.constructor===Object); //true
function Person(name) {
this.name = name;
}
alert(Person.prototype.constructor==Person); //true
參考:Douglas Crockford《JavaScript語言精粹》
http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html