玩轉JavaScript OOP[1]——複雜類型

来源:http://www.cnblogs.com/keepfool/archive/2016/06/06/5562613.html
-Advertisement-
Play Games

概述 在JavaScript中,我們可以使用函數、數組、對象,以及日期、正則等一些內置類型的實例,它們都是複雜類型的表現。從本質上講,這些複雜類型都是Object類型。本篇主要的內容有3點:函數、數組和對象。 函數 函數是JavaScript的一大重點,它非常的靈活。不像C#這種強類型語言,可以顯式... ...


概述

在JavaScript中,我們可以使用函數、數組、對象,以及日期、正則等一些內置類型的實例,它們都是複雜類型的表現。從本質上講,這些複雜類型都是Object類型。本篇將主要介紹三種Object類型的體現:函數、數組和對象。

函數

函數是JavaScript的一大重點,它非常的靈活。不像C#這種強類型語言,可以顯式地聲明"class",JavaScript沒有"class"的概念,但藉助函數我們可以實現"class"的概念。類和對象是面向對象編程的基礎,所以掌握函數是掌握JavaScript面向對象編程的前提。

定義函數

JavaScript的函數有兩種定義方式:函數聲明和表達式聲明。

方式1:函數聲明

// 函數聲明
function sum(a,b){
	return a + b;
}

var result = sum(3,5); // 8;

函數聲明function關鍵字後面跟著函數名稱,參數放在一對小括弧中,函數內容放在大括弧內。
這段代碼中,sum是函數的名稱,如果指定了return語句,則可以通過變數來接收。

方式2:表達式聲明

// 表達式聲明
var hello = function(){
	console.log('Hello!');
}
hello();

表達式聲明function關鍵字後面沒有函數名稱,這種函數也被稱作匿名函數,匿名函數通常會被一個變數引用。
這段代碼中,hello不是函數的名稱,它是一個指向匿名函數的指針變數。
函數可以沒有return語句,這時JavaScript引擎會自動地返回一個undefined。

兩種方式的區別

雖然這兩種方式比較相似,但它們有一個較大的區別——聲明的提升
使用方式1聲明的函數會被會被提升至函數所處上下文的頂部,使用方式2則不會。

下麵這段代碼在瀏覽器中是可以工作的,並且不會報錯。

var result = sum(3,5); // 8;

// JavaScript引擎將函數聲明提升到頂部
function sum(a,b){
	return a + b;
}

上面這段代碼會被JavaScript引擎解釋為下麵這段代碼。

function sum(a,b){
	return a + b;
}

var result = sum(3,5); // 8;

使用表達式聲明的函數不會被提升,下麵這段代碼會報錯。

// 會報錯:hello is not a function
hello();

var hello = function(){
	consol.log('Hello!');
}

函數聲明使得JavaScript引擎提前獲知了函數的名稱,匿名函數由於沒有名稱,JavaScript引擎無法對它進行提升。

小提示:無論使用哪種方式,應該先聲明函數再使用,這樣才不會出錯。

函數的類型

使用typeof查看函數的類型時,得到的結果是"function"。
在JavaScript中,函數是一種特殊的引用類型,所有非函數的引用類型使用typeof都會返回"object"。

image

之前提到了JavaScript只有一種複雜類型(引用類型)——Object類型,函數既然是引用類型,那麼怎麼證明他是屬於Object類型的呢?

使用instanceof操作符

雖然JavaScript沒有類的概念,但是它有構造函數的概念,JavaScript是通過構造函數來創建對象實例的。
instanceof操作符可以用來判斷某個構造函數的prototype屬性所指向的對象是否存在於另外一個要檢測對象的原型鏈上。
後面的文章會講到prototype和原型鏈,如果你不理解這句話,則可以將這個操作符看成C#中的is操作符(判斷對象是否為某個類的實例)。

下麵這幅圖揭示了sum函數是Function的實例,Function又是Object的實例,sum也是Object的實例。

image
Function()和Object()是JavaScript內置的兩個構造函數。

sum()函數同樣可以通過Function()函數來實現:

var sum = new Function('a','b', 'return a + b;');

image

Function()構造函數的前面幾個參數都表示函數的參數,最後一個參數表示函數的內容。
不管是函數參數還是函數內容,都是用字元串表示的,JavaScript引擎在運行時才需要先解析這種方式聲明的函數,才能確定其形式。
雖然Function()構造函數可用於創建函數,但不建議這麼做,因為它會使代碼難以理解和調試。

小提示:在JavaScript中,new後面接的肯定是一個構造函數,例如new Function()、new Object()。

函數的本質是數據

函數本質上是數據,這是一個比較重要的概念。
函數可以用表達式聲明,並將其賦給一個變數。
變數用於存儲數據,變數要麼存儲基礎類型的值,要麼存儲引用類型的地址。

下麵這段代碼,sum是一個變數,存儲的卻是函數指針。
同時,這個匿名函數被當成一般的值,並賦給了變數add。

var sum = function (a, b) {
	return a + b;
};

var add = sum;
add(6,4);	// 10

JavaScript的函數就是數據,但它們是一種特殊的數據:

  • 包含代碼
  • 這些代碼可以被執行或被調用

對象

使用基礎類型時,我們只能一個變數存儲一個值,如果要將多個值存儲在一個變數中,可以使用對象。
JavaScript中的對象是動態的,對象中包含屬性,屬性以key-value形式存在。
由於JavaScript的靈活性,使得我們可以為在任意地方指定對象的屬性,對象的屬性也可以被指定為任意類型。

創建對象

在使用對象前,我們應該先創建對象。
對象有兩種創建方式:使用{}Object()構造函數。

// 方式1:使用{}創建對象
var person = {
	name: 'keepfool',
	job: 'developer',
	say: function() {
		return 'Hello! I am ' + this.name + ', I am a ' + this.job;
	}
};

// 方式2:使用Object()構造函數
var player = new Object();
player.name = 'Stephen Cury';
player.age = 28;
player.play = function() {
	return 'I am ' + this.name + ', ' + this.age + ' years old, I play basketball very well!';
}

這兩種方式本質上沒有什麼區別,使用方式1聲明對象時,JavaScript引擎背後做的工作和new Object()是一樣的。
方式1相當於方式2的快捷方式,建議使用方式1來創建。

在對象初始化後,你可以在任意時間給對象追加新的屬性。

// 方式1:使用{}創建對象
var person = {
	name: 'keepfool',
	job: 'developer',
	say: function() {
		return 'Hello! I am ' + this.name + ', I am a ' + this.job;
	}
};

// 追加新的屬性
person.weigh = '70kg';
person.run = function() {
	return 'I am running!';
}

註意:person對象的say屬性是一個函數,當函數作為對象的一個屬性時,我們稱之為“方法”。
對象的屬性就是數據,JavaScript的屬性可以是方法,方法本質上是函數,從這個層面又印證了“函數就是數據”的說法。
say方法中用到了this,this是一個指針,它指向person對象本身,this.name即person.name。

訪問屬性

訪問對象屬性的方式也有兩種:使用object.propertyobject['property']

object.property方式:

image

object['property']方式:

image

註意:person的say屬性和player的play屬性都是方法,通過person.say和player.play得到的是方法的指針(函數的指針),使用()才是調用對象的方法。
由於數組也提供了[]方式訪問元素,為了區分數組和對象,建議使用object.property方式訪問屬性。

對象的類型

使用typeof查看對象的類型,得到的結果都是"object"。

image

使用instanceof檢測是否為Object類型,得到的結果都是true。

image

 

數組

在C#中,數組中的元素是同一個類型的,JavaScript則不然。
在JavaScript中,你可以在數組中存儲任意類型的值,數組元素可以是數字、字元、日期、對象、數組等等。
這和C#中的ArrayList有些相似。

創建數組

在JavaScript中,創建數組有兩種方式:

// 方式1:使用[]創建數組
var arr1 = [1,"Hello", true, {id : 1, name : "keepfool"}];

// 方式2:使用Array()構造函數創建數組
var arr2 = new Array(1, "Hello", true, {id : 1, name : "keepfool"});

方式1和方式2本質上是一樣的,在使用方式1聲明數組時,JavaScript引擎做的事情和new Array()也是一樣的。
方式1比方式2更加便捷直觀一些,建議使用方式1。

訪問數組元素

數組是一個有序的數據集合,通過[]索引器可以訪問數組元素。

image

數組的類型

使用typeof查看數組的類型時,得到的結果是"object"。

image

數組的檢測

如果你定義了多個變數,有些變數用於表示數組,有些變數用於表示數組。
將typeof操作符應用於對象或數組變數,得到的結果都是"object"。
我們怎麼區別哪個變數是對象,哪個變數時數組呢?有兩種方式可以鑒別。

方式1:使用instanceof

image


方式2:使用isArray()方法

image

數組是否為Object?

instanceof操作符檢測函數的類型是Object的,那麼數組也可以用這種方式來檢測。

image

所以數組本質上也是Object類型的。

複雜類型總結

  • 函數、對象和數組都是Object類型的實例,使用Instanceof操作符可以檢測它們
  • 函數的本質是數據,function是Function的實例,Function又是Object的實例
  • 對象是由屬性構成的,對象的屬性可以是任意類型的
  • 數組是有序的數據集合,數組元素可以是任意類型的,Array是Object的實例
【關註】keepfool


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 緩存是分散式系統中的重要組件,主要解決高併發,大數據場景下,熱點數據訪問的性能問題。提供高性能的數據快速訪問。 本文是緩存在分散式應用第二篇文章,介紹分散式緩存,Memcache,Redis,本地緩存(硬碟緩存,記憶體緩存)以及緩存在分散式系統中的架構示例。 ...
  • 緩存是分散式系統中的重要組件,主要解決高併發,大數據場景下,熱點數據訪問的性能問題。提供高性能的數據快速訪問。 本文是緩存在分散式應用第一篇文章,介紹緩存的原理,緩存的分類,緩存的設計,CDN緩存(原理,架構參考和技術實踐),反向代理緩存(原理,Squid架構實踐和常用代理緩存之間的比較)。 ...
  • Atitit.用戶許可權服務 登錄退出功能 參數說明 /com.attilax/user/loginOut.jsp?url="+url Utype=mer 作者:: ★(attilax)>>> 綽號:老哇的爪子 ( 全名::Attilax Akbar Al Rapanui 阿提拉克斯 阿克巴 阿爾 拉 ...
  • 一開始可能會寫得很亂,因為自己也不太清楚從哪裡入手,可能會直接將一些別人的心得羅列出來,後面我會在吸收了以後,找到了頭緒,然後整理歸納出自己的東西。 不多扯了,先摘一段別人的心得,原文鏈接http://www.cnblogs.com/Azula/p/4988949.html 一 . AbpBoots ...
  • 方法: 1、安裝tomcat1,過程為解壓縮。 2、拷貝壓縮後的文件,命名為tomcat2。 修改tomcat2中配置文件,tomcat1保持不變 server.xml, <Server port="8006" shutdown="SHUTDOWN"> 埠改為8006,tomcat1為8005 < ...
  • Pool對象的技術指標: 避免頻繁創建經常使用的稀有資源,提高工作效率. 控制閥值,很多情況下一些關鍵資源都有一個最佳併發數,超過這個拐點性能有可能急劇下降,也有可能繼續增大併發數性能不能提升. 安全的獲取對象和釋放對象(使用之後放回連接池) T對象實現時最好與Pool對象建立某種關聯,調用T對象實 ...
  • 前言 long long ago,大家普遍地認為JavaScript就是做一些網頁特效的、處理一些事件的。我身邊有一些老頑固的.NET程式員仍然停留在這種認知上,他們覺得沒有後端開發肯定是構建不了系統的。 編程語言和技術的結合使用,就像一個男人娶了好幾個妞一樣。在舊的時代,.NET是大房,JavaS... ...
  • 適配器模式主要用於當我們寫的代碼與舊代碼(可能不是我們寫的)無法相容時,做類型相容,這樣我們就可以輕鬆使用舊代碼中的功能了,這個模式和裝飾模式很像。 但二者還是有所區別的,裝飾模式主要是為了為類添加裝飾功能,將核心功能與裝飾功能分開。適配器模式主要是為了新舊代碼的相容,萬不得已才使用。 代碼如下: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...