JavaScript-函數基礎知識

函數定義/函數聲明

1. 自定義函數(命名式函數)
function fn() {}

2. 函數表達式(匿名函數)
var fun = function(){}

3. new Function('參數1', '參數2', ... ,'函數體')

// 參數:空;函數體:console.log(123)
var f = new Function('console.log(123)'); 
f(); // 函數調用

// 參數:a, b;函數體:console.log(123)
var f = new Function('a', 'b', 'console.log(a + b)'); 
f(1, 2);

4. 所有函數都是Function的實例(對象)
console.dir(f);
console.log(f instanceof Object); // true

函數的定義方式

<script>
    var f = new Function('a', 'b', 'console.log(a + b)'); 
    f(1, 2); // result: 3
</script>
  •  console.log(f instanceof Object); // true
  • console.log(f.prototype);

  • console.log(f.__proto__);

函數調用方式

1. 普通函數
function fn() {
  console.log(123);
}
fn(); // 調用方式一
fn.call(); // 調用方式二

2. 對象的方法
var o = {
    sayHi: function(){
        console.log('hello, world');
    }
}
o.sayHi(); // 函數調用(對象.方法名)

3. 構造函數
function Start() {};
new Start(); // 函數調用(實例化一個對象)

4. 綁定事件函數(匿名函數)
btn.onclick = function() {}; // 點擊按鈕時調用函數

5. 定時器函數
setInterval(function() {}, 1000) // 每隔1s執行一次

6. 立即執行函數 // 自動調用(自執行函數)
(function(){})() // 創建閉包

(function(){
    console.log('hello, world'); 
})()

匿名函數的用法(2種方式)

  • 賦值函數
  • 自執行函數

自執行函數

var b = function() {}; //聲明
b(); // 調用

自執行函數 = 聲明 + 調用

(b)();
//index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JS Test02...</title>
</head>
<body>
<script>
(function() {
    console.log(123);
})()
</script>
</body>
</html>

瀏覽器加載index.html,log窗口輸出123。函數沒有被調用,直接運行。自執行函數可直接使用,可用作創建命名空間、插件等。

自執行函數的調用方式常見的有三種:

//1.方式一
(function(){
    document.write('wo hao');
})();

//2.方式二
(function(){
    document.write('hello');
}());

//3.方式三
[function(){
    document.write('world');
}()];

參考鏈接:https://blog.csdn.net/weixin_44388523/article/details/86514627

實例:(知識點:自執行函數)

<script>
    for (var i = 0; i < 5; i++) {
        setTimeout(function() {
            console.log(i);
        }, i*1000);
    }
</script>

output:

5
5
5
5
5

原因:js中沒有塊級作用域,只有函數作用域。

1.首先執行for循環,設置5個定時器,定時器分別是0,1s,2s,3s,4s。

2.執行過程中需要打印i,i在for循環中定義。for循環執行結束後,i值爲5。每次打印值爲5

通過自執行函數解決以上問題

<script>
    for (var i = 0; i < 5; i++) {
        (function(i) {
            setTimeout(function() {
            console.log(i);
                }, i*1000);
        })(i);
    }
</script>

output:

0
1
2
3
4

方法2: ES6 使用let,塊級作用域。i只能在for循環內部使用,for循環外部無法使用i,i會依次增加。

<script>
    for (let i = 0; i < 5; i++) {
        setTimeout(function() {
            console.log(i);
        }, i*1000);
    }
</script>

output:

0
1
2
3
4

擴展:去掉function的參數i

console.log(i);向父元素尋找i,未找到。向for循環中找i,結果i爲5。

實例2(知識點:自執行函數)

// test.js

for (var i = 0; i < 5; i++) {
    setTimeout((function(i){
        console.log(i);
    })(i), i*1000);
}

在node環境中運行test.js,報錯:
timers.js:390 throw new ERR_INVALID_CALLBACK(); ^ TypeError [ERR_INVALID_CALLBACK]: Callback must be a function

原因:
node環境中,setTimeout函數第一參數必須是函數。自執行函數運行的結果不是函數。

//index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JS Test02...</title>
</head>
<body>
<script>
    for (var i = 0; i < 5; i++) {
        setTimeout((function(i){
            console.log(i);
        })(i), i*1000);
    }
</script>
</body>
</html>

瀏覽器打開index.html,運行結果如下:

0
1
2
3
4

瀏覽器中代碼解析如下:

setTimeout((function(i){ //沒有返回值
    console.log(i);
})(i), i*1000);

相當於
setTimeout(unddefined,i*1000);

不存在異步操作。

實例3(知識點:異步調用、Promise)

setTimeout(function() {
    console.log(1);
}, 0);

new Promise( r => {
    console.log(2);
    r();
    console.log(3);
}).then( data => {
    console.log(4);
})

console.log(5);

Event Loop 機制
主線程:2 3 5 4 1
異步
宏任務 setTimeout setInterval requestAnimationFrame
微任務 Promise mutationObserver interSectionObeser

1. setTimeout進入隊列任務
2. r() 進入任務隊列
3. 主線程執行完畢,依次執行微任務,宏任務

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章