[Effective JavaScript 筆記]第18條:理解函數調用、方法調用及構造函數調用之間的不同

来源:http://www.cnblogs.com/wengxuesong/archive/2016/05/25/5526533.html
-Advertisement-
Play Games

面向對象編程中,函數、方法、類的構造函數是三種不同的概念。 JS中,它們只是單個構造對象的三種不同的使用模式。 三種不同的使用模式 函數調用 函數的表現與行為一致,調用hello函數並將給定的實參綁定到username形參。 方法調用 js中的方法,是指對象的屬性恰好是函數而已。 這裡方法hello ...


面向對象編程中,函數、方法、類的構造函數是三種不同的概念。
JS中,它們只是單個構造對象的三種不同的使用模式。

三種不同的使用模式

函數調用

function hello(username){
	return 'hello,'+username;
} 
hello('world');//"hello,world"

函數的表現與行為一致,調用hello函數並將給定的實參綁定到username形參。

方法調用

js中的方法,是指對象的屬性恰好是函數而已。

var obj={
   hello:function(){
	return 'hello,'+this.username;
   },
   username:'world'
};
obj.hello();//"hello,world"

這裡方法hello是通過this變數來訪問obj對象的屬性的。 

this的指向是如何完成的呢?從上面的這個例子中,可能傾向於this變數被綁定到obj對象了,由於hello方法定義在obj對象中。
下麵看一個例子  

var obj2={
    hello:obj.hello,
    username:'han mei mei.'
}
obj2.hello();//"hello,han mei mei."

事實是,在方法調用的時候才由表達式來確定this變數的綁定情況。 

綁定到this變數的對象被稱為調用接收者(receiver)。
表達式obj.hello()在obj對象中查找名為hello的屬性,並將obj對象作為接收者,然後調用該屬性。
表達式obj2.hello()在obj2對象中查找名為hello的屬性,恰巧是obj.hello函數,但是接收者是obj2對象。
通常,通過某個對象調用方法將查找該方法並將對象作為該方法的接收者,也即this變數的對象。
按照上面的文字,畫了一張圖:
1464147280602
由於方法其實就是通過特定對象調用的函數,不知為何一個普通的函數不能引用this變數。

function hello(){
    return 'hello,'+this.username;
}

var obj1={
    hello:hello,
    username:'obj1'
}
var obj2={
    hello:hello,
    username:'obj2'
}
obj1.hello();//"hello,obj1"
obj2.hello();//"hello,obj2"

上面這段代碼的結構圖應該是這樣的。 

1464148054539

如果直接調用 

hello();//"hello,undefined"

一個非方法(nonmethod)的函數調用會將全局對象作為接收者,這時全局對象沒有名為username的屬性所以產生了undefined。 

如果方法中需要使用this變數,則將方法作為函數調用則毫無用處,因為沒有理由希望全局對象匹配調用對象中的方法。事實上,將this變數綁定到全局對象是有問題的,ES5嚴格模式將this變數的預設綁定值改為undefined

function hello(){
    'use strict';
    return 'hello,'+this.username;
}
hello();

結果如圖 

1464148382256
這樣做可以有助於更快地捕獲偶然地將方法錯誤地作為純函數使用的情況。

通過構造函數使用

就像方法和純函數一樣,構造函數也是由function運算符定義的。
function User(name,pwd){
     this.name=name;
     this.pwd=pwd;
}
var u=new User('li lei','asdfxov2-3409');
u.name;//"li lei"

與函數調用和方法調用不同的是,構造函數調用將一個全新的對象作為this變數的值,並隱式返回這個新對象作為調用結果。構造函數的主要職責是初始化該新對象。

提示

  • 方法調用將被查找方法屬性的對象作為調用接收者(this綁定)

  • 函數調用將全局對象(處於嚴格模式下則為undefined)作為其接收者。很少使用函數調用語法來調用方法。

  • 構造函數需要通過new運算符調用,並產生一個新的對象作為其接收者


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

-Advertisement-
Play Games
更多相關文章
  • 一、String類String類在java.lang包中,java使用String類創建一個字元串變數,字元串變數屬於對象。java把String類聲明的final類,不能有類。String類對象創建後不能修改,由0或多個字元組成,包含在一對雙引號之間。二、String類對象的創建字元串聲明:Str ...
  • 單例模式最初的定義出現於《設計模式》(艾迪生維斯理, 1994):“保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。” 特點:一是某個類只能有一個實例; 二是它必須自行創建這個實例; 三是它必須自行向整個系統提供這個實例。 一、經典實現 二、靜態構造函數實現 三、靜態變數實現 測試: ...
  • 市長信箱郵件查詢服務: 使用Elasticsearch 替代 Mysql 我在上一篇文章中實現了一個基於Springboot構建的web應用: 市長信箱郵件查詢服務. 應用將郵件信息抓取後保存在Mysql中,用以提供給搜索Web使用.Mysql雖然集成簡單,能快速實現功能, 但like查詢性能一般, ...
  • 學習要點: 1.大綱演算法 2.section和div 3.結構分析 主講教師:李炎恢 本章主要開始使用學慣用HTML5和CSS3來構建Web頁面,第一個項目採用PC端 固定佈局來實現。 一.大綱演算法 在HTML5中有一個很重要的概念,叫做HTML5大綱演算法(HTML5Outliner),它的用途是為 ...
  • 1、Table(Grid)參考地址 "https://github.com/samu/angular table" "https://github.com/daniel nagy/md data table" "https://github.com/davidjnelson/angular tabl ...
  • 引言 本文摘自《JavaScript設計模式與開發實踐》 在現實中,很多時候也有多種途徑到達同一個目的地。比如我們要去某個地方旅游,可以根據具體的實際情況來選擇出行的線路。 如果沒有時間但是不在乎錢,可以選擇坐飛機。 如果沒有錢,可以選擇坐大巴或者火車。 如果再窮一點,可以選擇騎自行車。 在程式設計 ...
  • 最近在研讀 《CSS SECRET》(CSS揭秘)這本大作,對 CSS 有了更深層次的理解,折騰了下麵這個項目: CSS3奇思妙想 -- Demo (請用 Chrome 瀏覽器打開,非常值得一看)。採用單標簽完成各種圖案,許多圖案與本文有關。 也希望覺得不錯的同學順手在我的 Github 點個 st ...
  • 一、原生js: 二、jquery版本: 採用deferred對象返回結果 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...