javascript 中function(){},new function(),new Function(),Function 摘錄

来源:https://www.cnblogs.com/7qin/archive/2018/09/07/9607532.html
-Advertisement-
Play Games

函數是JavaScript中很重要的一個語言元素,並且提供了一個function關鍵字和內置對象Function,下麵是其可能的用法和它們之間的關係。 function使用方式 最普通的function使用方式,定一個JavaScript函數。兩種寫法表現出來的運行效果完全相同,唯一的卻別是後一種寫 ...


函數是JavaScript中很重要的一個語言元素,並且提供了一個function關鍵字和內置對象Function,下麵是其可能的用法和它們之間的關係。

function使用方式

 var foo01 = function() //或 function foo01()
 {  
     var temp = 100;  
     this.temp = 200;  
     return temp + this.temp;  
 }  
 alert(typeof(foo01));  // function 
 alert(foo01());          // 300 

最普通的function使用方式,定一個JavaScript函數。兩種寫法表現出來的運行效果完全相同,唯一的卻別是後一種寫法有較高的初始化優先順序。在大擴號內的變數作用域中,this指代foo01的所有者,即window對象。

new function()使用方式

var foo02 = new function() {  
     var temp = 100;  
     this.temp = 200;  
     return temp + this.temp;  
 }  
 alert(typeof(foo02));    //object 
 alert(foo02.constructor());   //300   

//等價於
var temp =  function() {  
     var temp = 100;  
     this.temp = 200;  
     return temp + this.temp;  
 }  
var foo02 = new temp(); //沒有形參,可以省略圓括弧 var foo02 = new temp;
alert(typeof(foo02));    //object 
alert(foo02.constructor());   //300   

這是一個比較puzzle的function的使用方式,好像是定一個函數。但是實際上這是定一個JavaScript中的用戶自定義對象,不過這裡是個匿名類。這個用法和函數本身的使用基本沒有任何關係,在大擴號中會構建一個變數作用域,this指代這個作用域本身。(理解為實例化匿名類)

new Function()使用方式

var foo3 = new Function('var temp = 100; this.temp = 200; return temp + this.temp;');  

 alert(typeof(foo3));  //object
 alert(foo3());           //300

使用系統內置函數對象來構建一個函數,這和方法一中的第一種方式在效果和初始化優先順序上都完全相同,就是函數體以字元串形式給出。

Function()使用方式

var foo4 = Function('var temp = 100; this.temp = 200; return temp + this.temp;');  

 alert(typeof(foo4));     //function
 alert(foo4());              //300

這個方式是不常使用的,效果和方法三一樣,不過不清楚不用new來生成有沒有什麼副作用,這也體現了JavaScript一個最大的特性:靈活!能省就省。(不推薦)

註:如果構造函數沒有形參,javascript構造函數調用的語法是允許省略實參列表和圓括弧的。凡是沒有形參的構造函數調用都可以省略圓括弧

var o = new Object(); //等價於 var o = new Object;

-------------華麗的分割線-------------

javascript在用到對象時,完全沒有類的概念,但是編程的世界里,無奇不有,我們卻可以通過function構造出一種假想的類,從而實現javascript中類的構造。

比如,我們通過下麵的方法來構造一個類:

//java
class Book {
    private String name;
    private double price;
    public Book(name,price) {this.name=name;this.price=price;}
    public void setName(String name) { this.name = name;}
    public void setPrice(double price) {this.price = price;}
    public String getInfo() {...} 
}
Book book1 = new Book('java',13.3);

//javascript
function Book(name,price) {
    this.name = name;
    this.price = price;
    this.setName = function(name) {this.name = name;};
    this.setPrice = function(price) {this.price = price};
    this.getInfo = function() {return this.name + '  ' + this.price;};
}
var book1 = new Book('java',13.3);

Function是由function關鍵字定義的函數對象的原型

在javascript中,多出了一個原型的概念。所謂原型,其實就是一個對象的本質,但複雜就複雜在,原型本身也是對象,因此,任何一個對象又可以作為其他對象的原型。Function就相當於一個系統原型,可以把它理解為一種“基本對象類型”,是“對象”這個概念範疇類的基本數據類型。除了Function之外,其實還有很多類似的首字母大寫的對象原型,例如Object, Array, Image等等。有一種說法是:javascript中所有的一切都是對象(除了基本數據類型,其他的一切全是對象),所有的對象都是Object衍生出來的。

極其重要的prototype概念

prototype的概念在javascript中極其重要,它是javascript中完成上面說的“一切皆對象”的關鍵。有了prototype,才有了原型,有了原型,才有了javascript五彩繽紛的世界(當然,也有人說是雜亂的)。我們可以這樣去理解prototype:世界上本沒有javascript,上帝說要有Object,於是有了Object,可是要有Function怎麼辦?只需要對Object進行擴展,可是如何擴展?只需要用prototype……當然,這是亂扯的,不過在javascript中,只要是function,就一定會有一個prototype屬性。實際上確實是這樣

1 Function.prototype.show = function() {...}

在原型的基礎上通過prototype新增屬性或方法,則以該對象為原型的實例化對象中,必然存在新增的屬性或方法,而且它的內容是靜態不可重載的。原型之所以被稱為原型,可能正是因為這種不可重載的特質。

比如上面的這段代碼,會導致每一個實例化的function,都會具備一個show方法。而如果我們自己創建了一個類,則可以通過prototype將之轉化為原型:

function Book(name,price) {
    this.name = name;
    this.price = price;
    this.setName = function(name) {this.name = name;};
    this.setPrice = function(price) {this.price = price};
    this.getInfo = function() {return this.name + '  ' + this.price;};
}
Book.prototype.run = function(price) {console.log(this.price)};
var book1 = new Book('java',13.3);
book1.run();

這時,對於book1而言,Book就是原型,而該原型擁有一個run的原始方法,所以無論實例化多少個Book,每一個實例化對象都有run方法,而且該方法是不能被重載的,通過book1.run = function(){}是無效的。

為了和其他語言的類的定義方法統一,我們可以將這種原型屬性在定義類的時候,寫在類的構造裡面:

function Book(name,price) {
    this.name = name;
    this.price = price;
    this.setName = function(name) {this.name = name;};
    this.setPrice = function(price) {this.price = price};
    this.getInfo = function() {return this.name + '  ' + this.price;};
    Book.prototype.run = function(price) {console.log(this.price)};  //寫在類的構造裡面
}
//Book.prototype.run = function(price) {console.log(this.price)};
var book1 = new Book('java',13.3);
book1.run();

new Function()是函數原型的一個實例化

在理解了Function原型的概念之後,再來看new Function()就顯得很容易了。首先來看下我們是怎麼使用這種奇特的寫法的:

var log=new Function('log','console.log(log)');
log('hello javascript');   //hello javascript

其實等價於
function log(log){
     console.log(log);
}
log('hello javascript');//hello javascript

new Function(參數1,參數2,…,參數n,函數體),它的本意其實是通過實例化一個Function原型,得到一個數據類型為function的對象,也就是一個函數,而該變數(log)就是函數名(理解為:new Function實例化一個Function原型,得到 一個匿名函數 ,然後賦值給變數log)。

this在這類function中的指向

this在javascript中真的是無法讓我們捉摸透徹。但是有一個小竅門,就是:一般情況下,this指向的是當前實例化對象,如果沒有找到該對象,則是指向window。從使用上來講,我們應該排除new Function的討論,因為它和我們常用的函數聲明是一致的。

普通的函數中this的指向

函數聲明的時候,如果使用了this,那麼就要看是把該函數當做一個對象加以返回,還是以僅執行函數體。普通函數執行時,我們完全沒有引入對象、類這些概念,因此,this指向window。通過代碼來看下:

var msg;
function message(msg) {
    this.msg = msg;
}
message('ok');
alert(msg);

首先是聲明一個函數message,在函數中this.msg實際上就是window.msg,也實際上就是代碼開頭的msg。因此,當執行完message(‘ok’)的時候,開頭的全局變數msg也被賦值為ok。

通過function構造類時this的指向

如果function被構造為一個類,那麼必然存在該類被實例化的一個過程,如果沒有實例化,那麼該類實際上並沒有在程式中被使用。而一旦實例化,那麼this將指向實例化的對象。

var age = 3;
var cat1 = new function() {
    this.name = 'Tom';
    this.age = 2;
    this.weight = function(age) {
        var age = age * 2;
        var _age = this.age * 2;
        return 'weight by age:' + age + '; weight by this.age:' + _age;
    }(this.age);
    this.eye = new function() {
        this.size = '1.5cm';
        this.color = 'red';
    };
    this.catching = function(mouse) {
        return this.name + ' is catching ' + mouse;
    };
};
alert(cat1.weight);
alert(cat1.eye.color);
alert(cat1.catching('Jerry'));

上面代碼中標記了4處紅色的this的使用。根據我們的原則,this指向實例化對象,我們來對每一個this進行分解。

首先是cat1.weight,我使用了function(){}(),直接利用貓咪的年齡進行計算得出體重返回給weight屬性。

第一個this.age出現在function(){}(this.age),這個this.age實際上是一個傳值過程,如果你對我之前分析function(){}()比較瞭解的話,應該知道,this.age實際上是和前面this.age = 2指同一個,這裡的this.age的this,首先要去找它所在的function,然後看這個function是否被實例化,最後確認,確實被實例化為cat1,因此this=cat1。

第二個this.age出現在function(){this.age}()。同樣,你先需要對function(){}()再次深入瞭解,實際上,function(){}()就是執行一個函數而已,我們前面提到了,普通函數執行中this=window,所以,這裡的this.age實際上是var age = 3。

第三個this.color出現在new function(){this.color},這裡就比較好玩,由於有一個new,實際上也被實例化了,只不過是對匿名類的實例化,沒有類名,而且實例化僅可能出現這一次。因此,this.color的this要去找new function的主人,也就是this.eye,而this.eye的this=cat1,所以cat1.eye.color=’red’。

第四個this.name出現在function(){this.name},它出現在cacthing方法中,它既不是普通的函數執行,也不是實例化為對象,而是正常的類中的方法的聲明,因此this指向要去找它所在的function被實例化的對象,也就是cat1。

小結

本文雖然講了很多,但核心點實際上還是落在javascript的面向對象這個點上。javascript中雖然沒有明確的class的概念,那是因為它首先基於type這樣的基礎概念,並強調一切皆對象的這種思想。如果從哲學上講,javascript真正符合道生一,一生二,二生萬物的原則。不過本文沒有提到和繼承相關的內容,所有解釋也是我自己的一種理解方式,不代表真正的原理,讀者請自己通過其他途徑進行學習。

下篇轉載自:https://www.cnblogs.com/pizitai/p/6427433.html


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

-Advertisement-
Play Games
更多相關文章
  • 使用SSMS資料庫管理工具修改FOREIGN KEY約束 1、連接資料庫,選擇數據表-》右鍵點擊-》選擇設計(或者展開鍵,選擇要修改的外鍵,右鍵點擊,選擇修改,後面修改步驟相同)。 2、在表設計視窗中-》選擇要修改的外鍵列-》右鍵點擊-》選擇關係。 3、在外鍵關係彈出框中-》選中要修改的外鍵-》點擊 ...
  • mysql的連接錯誤,在網上查找到是編碼不匹配的原因, 直接在連接的URL後加上?useUnicode=true&characterEncoding=utf8就可以了 ...
  • 經常有初學者在博客和QQ問我,自己想往大數據方向發展,該學哪些技術,學習路線是什麼樣的,覺得大數據很火,就業很好,薪資很高。。。。。。。如果自己很迷茫,為了這些原因想往大數據方向發展,也可以,那麼我就想問一下,你的專業是什麼,對於電腦/軟體,你的興趣是什麼?是電腦專業,對操作系統、硬體、網路、服 ...
  • 關係型資料庫和非關係型資料庫區別 關係型資料庫 (1)關係型資料庫的特點: 一、關係型資料庫,是指採用了關係模型來組織數據的資料庫; 二、關係型資料庫的最大特點就是事務的一致性(innodb的功能) 1. 關係型資料庫支持事務 概念理解: 1)資料庫事務: 事務必須具備ACID特性,ACID是Ato ...
  • @property : iOS6 引入關鍵詞. @property name; 指示編譯器自動生成 name 的 setter 和 getter 方法 : - (NSString *)name; - (NSString *)name { return _name; } - (void)setName ...
  • 項目迭代開發的過程中,有用戶反映保存圖片到相冊崩潰,最終自己測試出,在iOS11以下的手機正常保存,而iOS11之後的手機則會出現反映的問題.列印錯誤信息如下: Google翻譯: 此應用程式已崩潰,因為它嘗試訪問隱私敏感數據,而無需使用說明。應用程式的Info.plist必須包含一個NSPhoto ...
  • 在OC中,字元串、數組、字典是最常見的對象類型,但是在這三個當中,字典的用法相對較少,因為字典的屬性和方法比較少,但是一個字典的用法比較複雜,因為在一個字典當中,既可以包含字元串,也可以包含數組,數組裡面的值是有序的,字典裡面的鍵值對是沒有序的,所以字典的使用往往和其他對象類型的使用混雜在一起,熟練 ...
  • 有話要說: 本篇主要總結了簡單的Android與js互相調用的方法。 在開發過程中遇到了需要在安卓中調用js方法的需求,於是將具體的實現過程總結成這篇博客。 效果: 其中“調用安卓方法”按鈕是html中的按鈕;“調用JS方法”按鈕是app中的按鈕。 本地HTML: 首先,在app根目錄新建一個ass ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...