亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

玩轉(zhuǎn)JavaScript OOP - 類(lèi)的實(shí)現(xiàn)詳解

 更新時(shí)間:2016年06月08日 09:41:35   投稿:jingxian  
下面小編就為大家?guī)?lái)一篇玩轉(zhuǎn)JavaScript OOP - 類(lèi)的實(shí)現(xiàn)詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

概述

當(dāng)我們?cè)谡務(wù)撁嫦驅(qū)ο缶幊虝r(shí),我們?cè)谡務(wù)撌裁矗?/p>

我們首先談?wù)摰氖且恍└拍睿簩?duì)象、類(lèi)、封裝、繼承、多態(tài)。

對(duì)象和類(lèi)是面向?qū)ο蟮幕A(chǔ),封裝、繼承和多態(tài)是面向?qū)ο缶幊痰娜筇匦浴?/p>

JavaScript提供了對(duì)象卻缺乏類(lèi),它不能像C#一樣能顯式地定義一個(gè)類(lèi)。

但是JavaScript的函數(shù)功能非常靈活,其中之一就是構(gòu)造函數(shù),結(jié)合構(gòu)造函數(shù)和原型對(duì)象可以實(shí)現(xiàn)”類(lèi)”。

對(duì)象和類(lèi)的概念

對(duì)象

“對(duì)象”是面向?qū)ο缶幊讨蟹浅V匾囊粋€(gè)概念,一個(gè)對(duì)象是一個(gè)“東西”(某個(gè)人或某件事)的描述。

人和事都來(lái)源于現(xiàn)實(shí)生活,我們對(duì)現(xiàn)實(shí)世界的認(rèn)知就是對(duì)人和事的認(rèn)知。

在編程的領(lǐng)域,代碼對(duì)于常人來(lái)說(shuō)是抽象的,代碼構(gòu)成的應(yīng)用是為了更好地解決現(xiàn)實(shí)世界的問(wèn)題。

在分析和設(shè)計(jì)階段,使用“對(duì)象”的概念能夠更好地反應(yīng)現(xiàn)實(shí)世界的問(wèn)題。

反過(guò)來(lái)說(shuō),代碼是包含一些邏輯的,這些邏輯用于描述業(yè)務(wù),業(yè)務(wù)是包含一些業(yè)務(wù)知識(shí)的,業(yè)務(wù)知識(shí)是通過(guò)對(duì)現(xiàn)實(shí)世界的理解和分析總結(jié)出來(lái)的,這些問(wèn)題是由現(xiàn)實(shí)世界的“對(duì)象”構(gòu)成的。

對(duì)象包含特征和行為,用OOP的術(shù)語(yǔ)來(lái)說(shuō),特征是對(duì)象的屬性,行為是對(duì)象的方法。

類(lèi)

在現(xiàn)實(shí)世界中,相似的對(duì)象可以按照一定的標(biāo)準(zhǔn)來(lái)分組。例如“蜂鳥(niǎo)”和“老鷹”都被劃分到鳥(niǎo)類(lèi),鳥(niǎo)類(lèi)不是一個(gè)具體的對(duì)象,它是人們根據(jù)“蜂鳥(niǎo)”、“老鷹”等那些具體的鳥(niǎo)分析出相似的特征和行為后,歸納出來(lái)的一個(gè)概念。類(lèi)相當(dāng)于一個(gè)模板,我們可以基于這個(gè)模板創(chuàng)建不同的具體的對(duì)象。

在C#中,我們可以定義一個(gè)鳥(niǎo)類(lèi)。

/// <summary>
/// 鳥(niǎo)類(lèi)
/// </summary>
public class Bird
{
  public void Fly()
  {
    Console.WriteLine("I can fly!");
  }
}

雖然JavaScript是一門(mén)面向?qū)ο缶幊陶Z(yǔ)言,但它沒(méi)有提供class的語(yǔ)法支持。

在JavaScript中,一切都是基于對(duì)象的,即使后面要講的“原型”也都是對(duì)象,JavaScript的繼承和重用也都是通過(guò)原型來(lái)實(shí)現(xiàn)的。

但是結(jié)合構(gòu)造函數(shù)和原型對(duì)象可以實(shí)現(xiàn)JavaScript的“類(lèi)”。

構(gòu)造函數(shù)

之前我們使用new Array()創(chuàng)建一個(gè)數(shù)組,使用new Object()創(chuàng)建一個(gè)對(duì)象,Array()和Object()是JavaScript內(nèi)置的兩個(gè)構(gòu)造函數(shù),盡管JavaScript沒(méi)有提供類(lèi),但我們可以將Array和Object理解為“類(lèi)”的概念。

需要注意的是,JavaScript的“類(lèi)”是由構(gòu)造函數(shù)實(shí)現(xiàn)的。

定義構(gòu)造函數(shù)

構(gòu)造函數(shù)也是函數(shù),定義構(gòu)造函數(shù)和其他函數(shù)并沒(méi)有語(yǔ)法上的區(qū)別。

唯一的區(qū)別是構(gòu)造函數(shù)的首字母應(yīng)該大寫(xiě),這也是JavaScript的編程規(guī)范。

以下定義了一個(gè)Person()構(gòu)造函數(shù),我們可以將它理解為Person類(lèi)。

function Person(){
	console.log('I am keepfool.');
}

JavaScript的“類(lèi)”和構(gòu)造函數(shù)是同時(shí)被定義的,在JavaScript中定義“類(lèi)”時(shí),就同時(shí)定義了構(gòu)造器。

使用構(gòu)造函數(shù)

JavaScript使用類(lèi)的方式和C#一樣,new關(guān)鍵字后面跟著構(gòu)造函數(shù)。

var p = new Person();

image

定義屬性和方法

現(xiàn)在我們已經(jīng)定義好了Person類(lèi),可以為Person類(lèi)添加一些屬性和方法。

定義屬性

在講JavaScript對(duì)象時(shí),我們講了對(duì)象的屬性設(shè)置和訪問(wèn)。
這段代碼展示了定義對(duì)象屬性的兩種方式:

var cat = {
	color: 'black'
};
cat.name = 'Tom';
console.log(cat.color);
console.log(cat.name);

使用this定義屬性

JavaScript類(lèi)的屬性定義方式則有些不同,在構(gòu)造函數(shù)中使用this關(guān)鍵字定義屬性:

function Person(name){
	this.name = name;
}

•第一行代碼,定義了Person類(lèi),并定義了構(gòu)造函數(shù)。

•第二行代碼,定義了name屬性。

創(chuàng)建并使用對(duì)象

以下2行代碼創(chuàng)建了兩個(gè)Person類(lèi)的對(duì)象

var p1 = new Person('James');
var p2 = new Person('Cury');

在Chrome控制臺(tái)中輸出p1.name和p2.name

image

p1和p2是兩個(gè)不同的對(duì)象,修改p1.name不會(huì)影響p2.name。

p1.name = 'Lebron James';

image

定義方法

首先,我們區(qū)分一下術(shù)語(yǔ)“函數(shù)”和“方法”,“函數(shù)”是獨(dú)立的單元,而“方法”是依賴(lài)于類(lèi)這個(gè)主體存在的。

使用this定義方法

在JavaScript中,類(lèi)的方法是定義在構(gòu)造函數(shù)中的函數(shù),在構(gòu)造函數(shù)中使用this關(guān)鍵字定義方法:

 

function Person(name) {
	// 定義屬性
	this.name = name;
	// 定義方法
	this.sayHello = function() {
		return 'Hello, I am ' + this.name;
	}
}

使用方法

在Chrome控制臺(tái)分別調(diào)用p1和p2對(duì)象的sayHello()方法

image

constructor屬性

當(dāng)創(chuàng)建一個(gè)對(duì)象時(shí),一個(gè)特殊的屬性被JavaScript自動(dòng)地分配給對(duì)象了,這個(gè)屬性就是constructor屬性。
在chrome控制臺(tái)輸入p1.constructor,可以看到p1對(duì)象的constructor屬性指向一個(gè)函數(shù)。

image

瞧瞧這個(gè)函數(shù)的內(nèi)容,這不正是Person()構(gòu)造函數(shù)嗎?

image

這表示我們也可以通過(guò)p1.constructor屬性創(chuàng)建對(duì)象,

var p3 = new p1.constructor('Steve Nash');

這行代碼闡述了一句話(huà):“我不關(guān)心p1對(duì)象是怎么創(chuàng)建的,但我想讓另一個(gè)對(duì)象如p1一樣創(chuàng)建!”

image

在Chrome控制臺(tái)使用instanceof操作符,可以看到p1、p2、p3都是Person類(lèi)的實(shí)例

image

另外,當(dāng)我們以{}方式創(chuàng)建對(duì)象時(shí),實(shí)際上也調(diào)用了Object()構(gòu)造函數(shù)。

var o = {};

這行代碼聲明了一個(gè)對(duì)象,盡管我們沒(méi)有設(shè)置任何屬性和方法,但JavaScript引擎默認(rèn)給它設(shè)置了constructor屬性。
o.constructor指向的是Object()構(gòu)造函數(shù),[native code]顯示了Object()是JavaScript內(nèi)置的函數(shù)。

image

原型對(duì)象

在JavaScript中,定義一個(gè)函數(shù)時(shí),函數(shù)就會(huì)擁有prototype屬性,構(gòu)造函數(shù)也不例外。
下圖說(shuō)明了Person()構(gòu)造函數(shù)的prototype屬性是一個(gè)對(duì)象,它是屬于函數(shù)的,我們稱(chēng)這個(gè)屬性為原型對(duì)象。
從Person類(lèi)的角度出發(fā),我們也可理解為prototype屬性是屬于Person類(lèi)的。

image

同時(shí)Person類(lèi)的實(shí)例是沒(méi)有prototype屬性的,上圖的p1.prototype是undefined,這說(shuō)明prototype屬性是共享的,這有點(diǎn)像C#中的靜態(tài)屬性。

設(shè)置prototype

既然prototype是一個(gè)對(duì)象,那就可以為它添加屬性和方法。

在函數(shù)的protpotype屬性上定義屬性和方法,與設(shè)置普通對(duì)象的屬性和方法沒(méi)什么區(qū)別。
下面的代碼為Person.prototype定義了屬性和方法。

 

function Person(name){
	this.name = name;
	this.sayHello = function() {
		return 'Hello, I am ' + this.name;
	}
}

// 在構(gòu)造函數(shù)的prototype對(duì)象上定義屬性和方法
Person.prototype.height = 176;
Person.prototype.run = function(){
	return 'I am ' + this.name + ', I am running!';
}

var p1 = new Person('James');

 使用prototype

在Person.prototype中定義的屬性和方法,可以直接被Person類(lèi)的實(shí)例使用,仍然是以object.property的方式使用。

image

需要特別注意的是,namesayHello()是屬于Person類(lèi)的實(shí)例,而heightrun()是不屬于Person類(lèi)的實(shí)例。

image

小技巧:通過(guò)hasOwnProperty方法可以查看對(duì)象是否包含某個(gè)屬性或方法。

自有屬性 vs. prototype的屬性

Person類(lèi)的實(shí)例既可以使用Person類(lèi)中的屬性,又可以使用Person.prototype中的屬性。
那么Person類(lèi)的屬性和Person.prototype的屬性有什么差別呢?

首先,我們可以將Person類(lèi)中的屬性和方法理解為“實(shí)例屬性”。
由于prototype是共享的,我們可以將prototype中的屬性和方法理解為“共享屬性”。

“實(shí)例屬性”和“共享屬性”的差別主要體現(xiàn)在性能上。
每創(chuàng)建一個(gè)Person的實(shí)例,就會(huì)產(chǎn)生一個(gè)name屬性和sayHello()方法的副本,而height屬性和run()方法則是所有實(shí)例共享一個(gè)副本。

既然如此,這意味著sayHello()方法可以提到prototype中。
另外,不同的Person實(shí)例height可能會(huì)不一樣,應(yīng)將它放到Person類(lèi)中更合理。

 

function Person(name,height){
	this.name = name;
	this.height = height;
}

Person.prototype.sayHello = function(){
	return 'Hello, I am ' + this.name + ', my height is ' + this.height + 'cm.';
}
Person.prototype.run = function(){
	return 'I am ' + this.name + ', I am running!';
}

var p1 = new Person('James',203);
var p2 = new Person('Cury',190);

 

image

類(lèi)的實(shí)現(xiàn)總結(jié)

 JavaScript沒(méi)有類(lèi),但構(gòu)造函數(shù)可以實(shí)現(xiàn)“類(lèi)”。

按照J(rèn)avaScript編程規(guī)范,構(gòu)造函數(shù)的首字母應(yīng)該大寫(xiě)。

“類(lèi)”的屬性和方法是用this.property方式定義在構(gòu)造函數(shù)中的。

在對(duì)象創(chuàng)建時(shí)JavaScript分配了constructor屬性給對(duì)象,constructor屬性是對(duì)象構(gòu)造函數(shù)的一個(gè)引用。

函數(shù)在定義時(shí)就已經(jīng)有了prototype屬性,prototype屬性也是一個(gè)對(duì)象。

prototype是共享的,定義在prototype上的屬性和方法可以被“類(lèi)”的實(shí)例使用。

如果屬性或方法能夠定義在prototype上,就不要定義在構(gòu)造函數(shù)上,使用prototype可以減少內(nèi)存開(kāi)銷(xiāo)。

以上這篇玩轉(zhuǎn)JavaScript OOP - 類(lèi)的實(shí)現(xiàn)詳解就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論