国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

跟我學習javascript的函數調用和構造函數調用

2019-11-20 11:15:51
字體:
來源:轉載
供稿:網友

一、函數調用
Function絕對是JavaScript中的重中之重。在JavaScript中,Function承擔了procedures, methods, constructors甚至是classes以及modules的功能。

在面向對象程序設計中,functions,methods以及class constructor往往是三件不同的事情,由不同的語法來實現。但是在JavaScript中,這三個概念都由function來實現,通過三種不同的模式。

最簡單的使用模式就是function 調用:

function hello(username) {   return "hello, " + username; } hello("Keyser Söze"); // "hello, Keyser Söze" 

二、方法的調用

而methods這一概念在JavaScript中的表現就是,一個對象的屬性是一個function:同樣的是函數,將其賦值給一個對象的成員以后,就不一樣了。將函數賦值給對象的成員后,那么這個就不在稱為函數,而應該叫做方法。

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

真正的行為是,調用本身才會決定this會綁定到哪個對象,即:
obj1.hello()會將this綁定到obj1,obj2.hello()則會將this綁定到obj2。記住一句話,誰調用,this就指向誰

正因為this綁定的這種規則,在下面的用法也是可行的:

function hello() {   return "hello, " + this.username; } var obj1 = {   hello: hello,   username: "Gordon Gekko" }; obj1.hello(); // "hello, Gordon Gekko" var obj2 = {   hello: hello,   username: "Biff Tannen" };_ obj2.hello(); // "hello, Biff Tannen" 

但是,在一個普通的函數中,如上面的hello函數,使用this關鍵字是不太好的方式,當它被直接調用的時候,this的指向就成了問題。在這種情況下,this往往被指向全局對象(GlobalObject),在瀏覽器上一般就是window對象。
而這種行為是不確定和沒有意義的。

所以在ES5標準中,如果使用了strict mode,那么this會被設置為undefined:

function hello() {   "use strict";   return "hello, " + this.username; } hello(); // error: cannot read property "username" of undefined 

以上這種做法是為了讓潛在的錯誤更快的暴露出來,避免了誤操作和難以找到的bug。
區別普通函數調用和方法調用,直接看這個例子就明確了。

var func = function() {  alert(this);};var o = {};o.fn = func;// 比較alert(o.fn === func);//true// 調用func();//[object Window]o.fn();//[object Object]

這里的運行結果是,兩個函數是相同的,因此打印結果是 true。但是由于兩個函數的調用是不一樣的,func 的調用,打印的是 [object Window],而o.fn 的打印結果是 [object Object]。

這里便是函數調用與方法調用的區別,函數調用中,this 專指全局對象 window,而在方法中 this 專指當前對象,即 o.fn 中的 this 指的就是對象o。

三、構造函數的調用

function的第三種使用模式就是講它作為constructor:

構造器中的this

我們需要分析創建對象的過程,方能知道this的意義. 如下面代碼:

 var Person = function() {  this.name = "小平果"; }; var p = new Person();

這里首先定義了函數Person,下面分析一下整個執行:

  • 程序在執行到這一句的時候,不會執行函數體,因此 JavaScript的解釋器并不知道這個函數的內容.
  • 接下來執行new關鍵字,創建對象,解釋器開辟內存,得到對象的引用,將新對象的引用交給函數.
  • 緊接著執行函數,將傳過來的對象引用交給this. 也就是說,在構造方法中,this就是剛剛被new創建出來的對象.
  • 然后為this 添加成員,也就是為對象添加成員.
  • 最后函數結束,返回this,將this交給左邊的變量.

分析過構造函數的執行以后,可以得到,構造函數中的this就是當前對象.

構造器中的return

在構造函數中return的意義發生了變化,首先如果在構造函數中,如果返回的是一個對象,那么就保留原意. 如果返回的是非對象,比如數字、布爾和字符串,那么就返回this,如果沒有return語句,那么也返回this. 看下面代碼:

 // 返回一個對象的 return var ctr = function() {  this.name = "趙曉虎";  return {  name:"牛亮亮"  }; }; // 創建對象 var p = new ctr(); // 訪問name屬性 alert(p.name); //執行代碼,這里打印的結果是"牛亮亮". 因為構造方法中返回的是一個對象,那么保留return的意義,返回內容為return后面的對象. 再看下面代碼: // 定義返回非對象數據的構造器 var ctr = function() {  this.name = "趙曉虎";  return "牛亮亮"; }; // 創建對象 var p = new ctr(); // 使用 alert(p); alert(p.name);

代碼運行結果是,先彈窗打印[object Object],然后打印”趙曉虎”. 因為這里 return 的是一個字符串,屬于基本類型,那么這里的return語句無效,返回的是this對象. 因此第一個打印的是[object Object]而第二個不會打印undefined.

function User(name, passwordHash) {   this.name = name;   this.passwordHash = passwordHash; } var u = new User("sfalken",   "0ef33ae791068ec64b502d6cb0191387"); u.name; // "sfalken" 

使用new關鍵將function作為constructor進行調用。和function以及method調用不一樣的是,constructor會傳入一個新的對象并將它綁定到this,然后返回該對象作為constructor的返回值。而constructor function本身的作用就是為了初始化該對象。

構造函數調用常犯的一個錯誤

興致勃勃地定義了下面這么個構造函數:

var Coder = function( nick ){ this.nick = nick; }; 

定義構造函數結束后呢?沒錯,趕緊實例化:

var coder = Coder( 'casper' ); 

這個coder兄弟叫什么名字?趕緊打印下:

console.log( coder.nick ); //undefined = =b 竟然是undefined!!再回過頭看看實例化的那個語句,不難發現問題出在哪里:少了個new var coder = Coder( 'casper' ); //當作普通的函數來調用,故內部的this指針其實指向window對象 console.log( window.nick); //輸出:casper var coder = new Coder( 'casper' ); //加上new,一切皆不同,this正確地指向了當前創建的實例 console.log( coder.nick ); //輸出:casper 

這樣的錯誤貌似挺低級的,但出現的概率挺高的,腫么去避免或減少這種情況的發生呢?
可以在內部實現里面動下手腳:

var Coder = function( nick ){   if( !(this instanceof Coder) ){     return new Coder( nick );   }     this.nick = nick; }; 

其實很簡單,實例化的時候,內部判斷下,當前this指向的對象的類型即可,如果非當前構造函數的類型,強制重新調用一遍構造函數。
突然覺得Coder這名字不夠洋氣?想用Hacker,好吧,我改。。。數了下,一共有三處要改,這不科學,有沒有辦法只把構造函數的名字改了就行?
當然有:

var Coder = function( nick ){   if( !(this instanceof arguments.callee) ){     return new arguments.callee( nick );   }   this.nick = nick; }; 

tips:據說在ES 5的嚴格模式下面arguments.callee會被禁用,不過僅當ES 5普及同時你指定了要使用嚴格模式,否則還是可以用的發散下思維。

以上就是本文的全部內容,希望對大家學習函數調用、方法調用和構造函數調用有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 汝州市| 项城市| 桑植县| 那曲县| 京山县| 延津县| 保山市| 上虞市| 灌阳县| 来宾市| 杭锦后旗| 腾冲县| 浦城县| 泰兴市| 奉贤区| 二手房| 湖口县| 建水县| 潞城市| 宁海县| 徐闻县| 营山县| 武邑县| 高清| 松桃| 中西区| 彭阳县| 东安县| 永修县| 家居| 茶陵县| 莱西市| 迁西县| 湛江市| 白河县| 兴义市| 万州区| 滁州市| 怀来县| 阜新| 鹤峰县|