JavaScript 語(yǔ)言是通過(guò)一種叫做 原型(prototype)的方式來(lái)實(shí)現(xiàn)面向?qū)ο缶幊痰?
對(duì)象(object)則是依靠 構(gòu)造器(constructor)利用 原型(prototype)構(gòu)造出來(lái)的尝苇。
上面說(shuō)的這一點(diǎn)很重要 需要細(xì)細(xì)思考 拋棄以前的的面向?qū)ο蟮墓逃心J健?br>
在這里先說(shuō)一下幾個(gè)概念
構(gòu)造函數(shù)什么削葱,其實(shí)就是一個(gè)函數(shù),但是在調(diào)用的時(shí)候使用new關(guān)鍵字严卖,然后我們就可以獲取一個(gè)新的對(duì)象了
function Student(name) {
this.name = name;
this.hello = function () {
alert('Hello, ' + this.name + '!');
}
}
使用構(gòu)造函數(shù)創(chuàng)造的對(duì)象還會(huì)繼承構(gòu)造器(constructor)巍佑,
xiaoming.constructor === Student.prototype.constructor; // true
Student.prototype.constructor === Student; // true
Object.getPrototypeOf(xiaoming) === Student.prototype; // true
xiaoming instanceof Student; // true
還有一點(diǎn)需要聲明的是通過(guò)構(gòu)造函數(shù)生成的對(duì)象是沒(méi)有prototype屬性的稼虎,而且構(gòu)造函數(shù)中的屬性其實(shí)是每一個(gè)對(duì)象單獨(dú)擁有送爸,但是如果說(shuō)有一個(gè)函數(shù)都是一樣的,那么我們可以直接設(shè)置構(gòu)造函數(shù)的prototype顷编,如下
function Student(name) {
this.name = name;
}
Student.prototype.hello = function () {
alert('Hello, ' + this.name + '!');
};
一般來(lái)說(shuō)是放一些函數(shù)和靜態(tài)值戚炫,也就是說(shuō)不會(huì)改變的東西
上面說(shuō)的這些其實(shí)只是簡(jiǎn)單的說(shuō)了一下JS創(chuàng)造類的方法
那么我們?nèi)绾螌?shí)現(xiàn)繼承呢
下面我先放一段別的地方粘貼過(guò)來(lái)的方法
function Foo() {
this.value = 42;
}
Foo.prototype = {
method: function() {}
};
function Bar() {}
// 設(shè)置Bar的prototype屬性為Foo的實(shí)例對(duì)象
Bar.prototype = new Foo();
Bar.prototype.foo = 'Hello World';
// 修正Bar.prototype.constructor為Bar本身
Bar.prototype.constructor = Bar;
var test = new Bar() // 創(chuàng)建Bar的一個(gè)新實(shí)例
// 原型鏈
test [Bar的實(shí)例]
Bar.prototype [Foo的實(shí)例]
{ foo: 'Hello World' }
Foo.prototype
{method: ...};
Object.prototype
{toString: ... /* etc. */};
這里面實(shí)現(xiàn)了簡(jiǎn)單的繼承
在這里我需要先插一些題外話
這里先說(shuō)一下 this 在函數(shù)中表示調(diào)用對(duì)象或者全局對(duì)象, 在構(gòu)造函數(shù)中表示新對(duì)象媳纬,當(dāng)然this對(duì)象也可能發(fā)生變換 比如我們使用 call或者apply就會(huì)直接綁定到第一個(gè)參數(shù)上面
所以
function PrimaryStudent(props) {
// 調(diào)用Student構(gòu)造函數(shù)双肤,綁定this變量:
Student.call(this, props);
this.grade = props.grade || 1;
}
但是調(diào)用了構(gòu)造函數(shù)不等于就已經(jīng)繼承了,我們還需要改變prototype屬性
Nodejs 實(shí)現(xiàn)繼承
Node提供了一種超級(jí)便利的繼承工具 如下使用
var util = require("util");var events = require("events");function MyStream() { events.EventEmitter.call(this);}util.inherits(MyStream, events.EventEmitter);MyStream.prototype.write = function(data) { this.emit("data", data);}var stream = new MyStream();console.log(stream instanceof events.EventEmitter); // trueconsole.log(MyStream.super_ === events.EventEmitter); // truestream.on("data", function(data) { console.log('Received data: "' + data + '"');})stream.write("It works!"); // Received data: "It works!"