Js基礎知識4-函數的三種創建、四種調用(及關於new function()的解釋)

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

在js中,函數本身屬於對象的一種,因此可以定義、賦值,作為對象的屬性或者成為其他函數的參數。函數名只是函數這個對象類的引用。 函數定義 從技術上講,這是一個函數表達式。但不推薦使用,因為這種語法會導致解析兩次代碼。第一次是解析常規javascript代碼,第二次解析傳入構造函數中的字元串,影響性能。 ...


在js中,函數本身屬於對象的一種,因此可以定義、賦值,作為對象的屬性或者成為其他函數的參數。函數名只是函數這個對象類的引用。

函數定義

 1 // 函數的三種創建方法(定義方式)
 2 function one(){                                 // 函數聲明語句,不屬於任何對象,始終預設為全局對象
 3 console.log("第一個函數")
 4 //預設有一個return this,返回函數中的內容
 5 }
 6 one();      //必須調用;可以在函數聲明前調用(預處理變異機制)                       
 7 
 8 var fn=function(){                               //函數定義表達式
 9 console.log("第二個函數")
10 }
11 fn(); //必須先聲明再調用                                 
12 
13 var fun=new Function(console.log("第三個函數"));    //Function構造函數 無需調用,會自調  
//實際一般應這樣寫:var newFun = new Function("x","return alert(x)");
//[註意]Function構造函數無法指定函數名稱,它創建的是一個匿名函數。

從技術上講,這是一個函數表達式。但不推薦使用,因為這種語法會導致解析兩次代碼。第一次是解析常規javascript代碼,第二次解析傳入構造函數中的字元串,影響性能。

var sum = new Function('num1','num2','return num1 + num2');
//等價於
var sum = function(num1,num2){
    return num1+num2;
}

[註意]並不是所有的函數都可以成為構造函數 

1 var o = new Math.min();//Uncaught TypeError: Math.min is not a constructor

【重覆聲明】變數的重覆聲明是無用的,不會覆蓋之前同一作用域聲明的變數,但函數的重覆聲明會覆蓋前面的聲明的同名函數或同名變數

//變數的重覆聲明無用
var a = 1;
var a;
console.log(a);//1
1 //覆蓋同名變數
2 var a;
3 function a(){
4     console.log(1);
5 }
6 a();//1
1 //覆蓋同名函數
2 a();//2
3 function a(){
4     console.log(1);
5 }
6 function a(){
7     console.log(2);
8 }

【刪除】函數聲明語句創建的變數無法刪除,這一點和變數聲明一樣。

1 function foo(){
2     console.log(1);
3 }
4 delete foo;//false
5 console.log(foo());//1

———————————————————

函數調用

javascript一共有4種調用模式:函數調用模式、方法調用模式、構造器調用模式和間接調用模式

【1】函數調用模式

  當一個函數並非一個對象的屬性時,那麼它就是被當做一個函數來調用的。對於普通的函數調用來說,函數的返回值就是調用表達式的值。

1 function add(x,y){
2     return x+y;
3 }
4 var sum = add(3,4);
5 console.log(sum)//7

使用函數調用模式調用函數時,非嚴格模式下,this被綁定到全局對象;在嚴格模式下,this是undefined

function add(x,y){
    console.log(this);//window
}    
add();//window
function add(x,y){
    'use strict';    //嚴格模式
    console.log(this);//undefined
}    
add();//undefined

因此,’this’可以用來判斷當前是否是嚴格模式

var strict = (function(){return !this;}());

【重寫】因為函數調用模式的函數中的this綁定到全局對象,所以會發生全局屬性被重寫的現象

1 var a = 0;
2 function fn(){
3     this.a = 1;
4 }
5 fn();
6 console.log(this,this.a,a);//window 1 1

【2】方法調用模式

當一個函數被保存為對象的一個屬性時,我們稱它為一個方法。當一個方法被調用時,this被綁定到該對象。如果調用表達式包含一個提取屬性的動作,那麼它就是被當做一個方法來調用。

var o = {
    m: function(){
        console.log(1);
    }
};
o.m();//1

方法可以使用this訪問自己所屬的對象,所以它能從對象中取值或對對象進行修改。this到對象的綁定發生在調用的時候。通過this可取得它們所屬對象的上下文的方法稱為公共方法。

var o = {
    a: 1,
    m: function(){
        return this;
    },
    n: function(){
        this.a = 2;
    }
};
console.log(o.m().a);//1
o.n();
console.log(o.m().a);//2

和變數不同,關鍵字this沒有作用域的限制,嵌套的函數不會從調用它的函數中繼承this。如果嵌套函數作為方法調用,其this的值指向調用它的對象。如果嵌套函數作為函數調用,其this值不是全局對象(非嚴格模式下)就是undefined(嚴格模式下)

var o = {
    m: function(){
         function n(){
             return this;
         }
         return n();
    }
}
console.log(o.m());//window
var o = {
    m: function(){
         function n(){
             'use strict';
             return this;
         }
         return n();
    }
}
console.log(o.m());//undefined

如果想訪問這個外部函數的this值,需要將this的值保存在一個變數里,這個變數和內部函數都同在一個作用域內。通常使用變數_this、that或self來保存this

var o = {
    m: function(){
        var self = this;
        console.log(this === o);//true
         function n(){
             console.log(this === o);//false
             console.log(self === o);//true
             return self;
         }
         return n();
    }
}
console.log(o.m() === o);//true

【3】構造函數調用模式

  如果函數或者方法調用之前帶有關鍵字new,它就構成構造函數調用

function fn(){
    this.a = 1;
};
var obj = new fn();
console.log(obj.a);//1

如果構造函數調用在圓括弧內包含一組實參列表,先計算這些實參表達式,然後傳入函數內

function fn(x){
    this.a = x;
};
var obj = new fn(2);
console.log(obj.a);//2

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

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

[註意]儘管構造函數看起來像一個方法調用,它依然會使用這個新對象作為調用上下文。也就是說,在表達式new o.m()中,調用上下文並不是o

var o = {
    m: function(){
        return this;
    }
}
var obj = new o.m();
console.log(obj,obj === o);//{} false
console.log(obj.constructor === o.m);//true

構造函數通常不使用return關鍵字,它們通常初始化新對象,當構造函數的函數體執行完畢時,它會顯式返回。在這種情況下,構造函數調用表達式的計算結果就是這個新對象的值

function fn(){
    this.a = 2;
}
var test = new fn();
console.log(test);//{a:2}

如果構造函數使用return語句但沒有指定返回值,或者返回一個原始值,那麼這時將忽略返回值,同時使用這個新對象作為調用結果

function fn(){
    this.a = 2;
    return;
}
var test = new fn();
console.log(test);//{a:2}

如果構造函數顯式地使用return語句返回一個對象,那麼調用表達式的值就是這個對象

var obj = {a:1};
function fn(){
    this.a = 2;
    return obj;
}
var test = new fn();
console.log(test);//{a:1}

【4】間接調用模式

  javascript中函數也是對象,函數對象也可以包含方法。call()和apply()方法可以用來間接地調用函數。

  這兩個方法都允許顯式指定調用所需的this值,也就是說,任何函數可以作為任何對象的方法來調用,哪怕這個函數不是那個對象的方法。兩個方法都可以指定調用的實參。call()方法使用它自有的實參列表作為函數的實參,apply()方法則要求以數組的形式傳入參數。

var obj = {};
function sum(x,y){
    return x+y;
}
console.log(sum.call(obj,1,2));//3
console.log(sum.apply(obj,[1,2]));//3

(函數返回值、函數參數、函數屬性、函數方法)另開篇章

js的運行機制問題:(聲明提升) 
1、在js中js引擎會優先解析var變數和function定義!在預解析完成後從上到下逐步進行! 
2、解析var變數時,會把值存儲在“執行環境”中,而不會去賦值,值是存儲作用!例如: 
alert(a); var a = 2; 這時會輸出undifiend,意思是沒有被初始化沒有被賦值! 
這並不是沒有被定義,錯誤了的意思! 
3、在解析function時會把函數整體定義,這也就解釋了為什麼在function定義函數時為什麼可以先調用後聲明瞭!其實錶面上看是先調用了,其實在內部機制中第一步實行的是把以function方式定義的函數先聲明瞭(預處理)

//*****************上篇出自:https://blog.csdn.net/luanpeng825485697/article/details/77010261

//*****************下篇出自:https://www.cnblogs.com/hss-blog/articles/9358251.html

//js中只有new Function沒有new function,或者我理解你說的new function是指實例化一個對象
//new Function的作用是從字元串中創建一個匿名方法,如下:
var newFun = new Function("alert(1)");
nweFun();        //彈出1
 
//如果你說的new function是實例化一個對象,那麼代碼如下:
function cls(){
    this.helloWord = function(){
        alert("hello Word!");
    }
}
var clsObj = new cls();
clsObj.helloWord();        //彈出hello Word!
//這裡的cls這個你應該要把他看成面向對象裡面的類,而不是js裡面的方法。
//當然本質上他就是一個方法,而且你也可以cls()這樣直接調用。
//更多js面向對象的東西我就不細說了,你可以自行百度。
 
//直接定義個function,然後調用,代碼如下:
function fun(){
    alert("hello Word!");
}
fun();            //彈出hello Word!
//這裡的方法你應該看成面向對象裡面的靜態方法,而不是面向對象裡面的類。
//當然他也確實是一個類,你也可以new fun()來調用。
//但是new fun()得到的對象沒有任何方法。

//其實關於new function 應該是這樣的( 更準確的說應該是new function()
var clsObj = new function()
{
this.helloWord = function(){
alert("hello Word!");
}
}
clsObj.helloWord(); //彈出hello Word!
//是實例化一個對象(匿名函數),這樣寫的好處是可以防止沒有new調用函數

 


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

-Advertisement-
Play Games
更多相關文章
  • 一、無繼承性的屬性 1、display:規定元素應該生成的框的類型 2、文本屬性: vertical-align:垂直文本對齊 text-decoration:規定添加到文本的裝飾 text-shadow:文本陰影效果 white-space:空白符的處理 unicode-bidi:設置文本的方向 ...
  • 本博文歸納在 Vue 學習過程中, Vue-cli 工具的使用說明。除此之外還通過 Vue-cli 工具將之前 Vuejs 基本語法當中實現的 todoList 進行重構。 安裝 創建 創建一個基於 webpack 模板的新項目,在此之前,先 cd Desktop 到桌面路徑 各選項簡介 安裝完畢之 ...
  • 《一統江湖的大前端》系列是自己的學習筆記,旨在介紹javascript在非網頁開發領域的應用案例和發現各類好玩的js庫,不定期更新。如果你對前端的理解還是寫寫頁面綁綁事件,那你真的是有點OUT了,前端能做的事情已經太多了, , , , , , 甚至 ,什麼火就搞什麼,絕對是專業的 蹭熱點小能手 。 ...
  • 字元串的生成轉換 你可以將任何類型的數據都轉換為字元串,你可以用下麵三種方法的任何一種: 字元串轉化為其他類型 js提供了parseInt()和parseFloat()兩個轉換函數,Number也可以實現轉化 字元的操作 字元串增刪查改 字元串比較 比較兩個字元串,比較是規則是按照字母表順序比較的 ...
  • todoList 結合之前 Vuejs 基礎與語法 使用 v-model 雙向綁定 input 輸入內容與數據 data 使用 @click 和 methods 關聯事件 使用 v-for 進行數據迴圈展示 <!DOCTYPE html> <html lang="en"> <head> <meta ...
  • 剛開始學JQuery寫的如有錯誤歡迎批評指正 JQuery擁有的選擇器可以讓我們更快更方便找到想要的元素,然後對相應的元素進行操作 簡單介紹一下一些常用的選擇器: 1.基本選擇器: 2.層級選擇器: 層級函數 3.過濾選擇器: 4.內容選擇器: 5.屬性選擇器: 6.子元素選擇器: 7.表單選擇器: ...
  • 全棧工程師也可以叫web 前端 H5主要是網站 app 小程式 公眾號這一塊 HTML篇 html(超文本標記語言,標記通用標記語言下的一個應用。) “超文本”就是指頁面內可以包含圖片、鏈接,甚至音樂、程式等非文字元素。 超文本標記語言的結構包括“頭”部分(英語:Head)、和“主體”部分(英語:B ...
  • 我主要進行對日期數據進行查看使用,有數據的顯示顏色、沒有數據可以不選 更多可以查看官方網站:http://www.daterangepicker.com/#examples ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...