JS函數深入

来源:https://www.cnblogs.com/chenyingying0/archive/2020/01/03/12143434.html
-Advertisement-
Play Games

函數的本質是對象 三種定義方式 1、 字面量=function聲明 function add() { // body... } add(); 2、 var賦值表達式 var add = function (argument) { // body... }; add(); var add = func ...


函數的本質是對象

三種定義方式

1、  字面量=function聲明

            function add() {
                // body...
            }
            add();

2、  var賦值表達式

            var add = function (argument) {
                // body...
            };
            add();
            var add = function fn(argument) {
                // body...
                fn();
                add();
            };
            add();
            fn();//會報錯,只能在函數體內調用

3、  構造函數

    var add = new Function('num1', 'num2', 'return num1 + num2;');
            add();

三種定義方式區別:

字面量=function聲明:預載入時add=function

    console.log(add());
    function add() {
        return 1;
}

var賦值表達式:預載入時add=undefined

    console.log(add());
    var add = function () {
        return 1;
};

構造函數:少用

 


 

雜七雜八的知識點:

JS中沒有塊級作用域,所以不會在if中發生預解析,在外部預解析的時候,if中聲明的所有函數都會被提前,所以無法達到按需定義的目的。

內部函數可以訪問外部函數的變數(作用域鏈的機制)

 


 

案例:寫出一個加法(add)函數,併在其內部定義一個函數(isNumber),用來判斷add的參數是否可以轉化為數字類型進行相加,

如果可以,就在頁面中輸出結果;

如果不能就退出add,給出提示“請傳入數字類型的參數”

function add(num1,num2){
    if(isNaN(num1) || isNaN(num2)){
        alert('請傳入數字類型的參數');
        return;
    }else{
        return parseInt(num1)+parseInt(num2);
    }
}

var num1=prompt('請輸入數字1');

var num2=prompt('請輸入數字2');

alert(add(num1,num2));

案例:匿名函數也是函數,當它自執行的時候會創建函數作用域,它裡面的變數和函數都是局部的,當匿名函數執行完畢後會被銷毀。所以我們在外面訪問不到add

    function () {
        function add(num1,num2){
            return num1+num2;
        }
    }();
    document.write(add(1,2));//報錯

匿名函數自執行方式:

    var add = function () {
        console.log(1);
    }();

    (function () {
        console.log(1);
    })();

    !+-~function () {
        console.log(1);
    }();

遞歸調用:遞歸調用就是自己調用自己,但切記一定要有終止條件,否則函數將無限遞歸下去

    function factorial(num) {
        if (num <= 1) return 1;
        return num * factorial(num - 1);
        // return 5 * 4! = 5 * 4 * 3! =... 5 * 4 * 1!
    }
    console.log(factorial(5));

方法的調用:

    document.onclick = function () {
        console.log('你點擊了文檔!');
    };
    document.onclick();
    var operation = {
        add: function (num1, num2) {
            return num1 + num2;
        },
        subtract: function (num1, num2) {
            return num1 - num2;
        },
        '@': function () {
            console.log('@');
        },
        key: function () {
            // body...
        }
    };
    console.log(operation.add(1, 2));
    console.log(operation['@'](1, 2)); //@符比較特別
    var key = 'add';
    console.log(operation[key](1, 2));

鏈式調用

    var operation = {
        add: function (num1, num2) {
            console.log(num1 + num2);
            return this;
        },
        subtract: function (num1, num2) {
            console.log(num1 - num2);
            return this;
        },
        '@': function () {
            console.log('@');
        },
        key: function () {
            // body...
        }
    };
    operation.add(1, 2).subtract(2, 1);

間接調用:

對象沒有call和apply方法,只有函數有

call和apply的唯一區別就在它們傳參的方式上

apply可以將數組和類數組一次性的傳遞進函數中,call只能一個一個的傳;

    var name = 'xm';
    var person = {};
    person.name = 'xh';
    person.getName = function () {
        return this.name;
    };
    console.log(person.getName()); //this指向person
    console.log(person.getName.call(window)); //this指向window
    console.log(person.getName.apply(window)); //this指向window

    function add(num1, num2) {
        return num1 + num2;
    }
    console.log(add(1, 2));
    var datas = [1, 2];
    console.log(add.call(window, 1, 2));
    console.log(add.apply(window, datas)); //apply(ele,[])

輸出:'xm', [object Object]

person()就是普通函數的調用,返回值是return後面的內容:'xm' ; new person()是將person作為構造函數調用,返回的永遠是對象 ; document.write沒法輸出對象,它會嘗試著將其轉換成字元串輸出

 

輸出:undefined

call可以改變函數中this的指向,這裡在調用方法的時候將其this改為了window,所以this.value就變成了window.value,而window.value沒有定義過,所以為undefined

 


 

函數的參數:

function add() {
    if (arguments.length == 0) return;
    var sum = 0;
    for (var i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return sum;
}
console.log(add());
console.log(add(1, 2, 3, 4, 5));

arguments

類數組,實質是類

function fn(name) {
    arguments[0] = '';
    console.log(name);
}
fn('xm');//沒有輸出

arguments.callee 指代函數本身,多用於遞歸

計算階乘方法一:

function factorial(num) {
    if (num <= 1) return 1;
    return num * factorial(num - 1);
}
console.log(factorial(5));

計算階乘方法二:

function factorial(num) {
    if (num <= 1) return 1;
    return num * arguments.callee(num - 1);
}
console.log(jiecheng(5));

計算階乘方法三:

var jicheng = function fn(num) {
    if (num <= 1) return 1;
    return num * fn(num - 1);
};
console.log(jicheng(5));

判斷傳入實參的個數是否與形參相等

arguments.length實參個數

add.length形參個數

 

function add(num1, num2) {
    if (arguments.length != add.length) throw new Error('請傳入' + add.length + '個參數!');
    return num1 + num2;
}
console.log(add(1, 1));
console.log(add(1));
console.log(add(1, 2, 3));

案例:

輸出:1,1,1,1,2,3

1、 count()()這樣調用,每次都會創建一個新的局部作用域,num的值會不斷地被初始化為1

2、 return num++表示先返回num的值,再將num加1

3、 先將count()賦給fn,此時count()只調用了一次,接下來多次調用fn()的時候,count函數並沒有多次調用,num只會在count函數調用的時候被初始化,所以多次調用fn()的時候num不會被多次初始化;由於fn相當於count函數的內層函數(var fn=count();這行代碼執行後,就調用了count(),調用count後就將裡面的函數賦值給了fn,所以說fn就相當於函數的內層函數了。),可以訪問count中的變數num,所以多次調用fn函數,會將num的值累加;


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

-Advertisement-
Play Games
更多相關文章
  • 案例貪吃蛇,把封裝的函數移動到js文件中 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>title</title> <style> .map { width: 800px; height: 600px; b ...
  • 案例:貪吃蛇小游戲 可以玩的小游戲,略複雜,過了2遍,先pass吧 先創建構造函數,再給原型添加方法。分別創建食物,小蛇和游戲對象。 食物,小蛇的橫縱坐標,設置最大最小值,運動起來的函數,按上下左右鍵的處理函數,吃到的處理函數 <!DOCTYPE html> <html lang="en"> <he ...
  • "^[0-9]*[1-9][0-9]*$" //正整數"^((-\d+)|(0+))$" //非正整數(負整數 + 0)"^-[0-9]*[1-9][0-9]*$" //負整數"^-?\d+$" //整數"^\d+(\.\d+)?$" //非負浮點數(正浮點數 + 0)"^(([0-9]+\.[0- ...
  • Object 是javascript 父對象 function F(){ //自定義函數 } alert(F.prototype); //函數原型是object對象 alert(F.prototype instanceof Object); //true 閉包 全局變數在函數內部可以訪問 funct ...
  • 該篇僅是本人學習前端時,做的備忘筆記: 一、背景圖片設置: 設置背景圖時的css代碼:background-image:url(圖片的url路徑); ps:設置好這個背景後請一定要設置該背景圖片的大小和該背景圖片的顯示區域,css樣式設置如下: e.g. background-size:36px 3 ...
  • 查看對象的方法,繼續控制台輸出,如圖: hasOwnProperty():返回一個布爾值,指示對象自身屬性中是否具有指定的屬性(也就是,是否有指定的鍵)。 isPrototypeOf():用於測試一個對象是否存在於另一個對象的原型鏈上。 toString():返回一個表示該對象的字元串。 value ...
  • 先放圖(好吧比較挫) 方法一:最容易版 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <title>簡易計算器</title> <style> body { background-color: #eee; } ...
  • 想瞭解數組有哪些原生方法,控制台輸出,如圖: length:數組的實例屬性,返回或設置一個數組中的元素個數。 toString():可以把數組轉換成字元串,並返回結果。 toLocaleString():返回數組中每個元素的本地化表示形式。 let a = [1234,'hello',21]; a. ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...