JavaScript 核心觀念(46)-函式以及 This 的運作-函式以及 This 的運作 - 課後練習

前言

接下來這一章節又來到課後練習。

第一題

請問以下 a 函式將會出現什麼訊息?

1
2
3
4
5
function a (fu) {
fu();
};

a('小明');
  1. 小明
  2. undefined
  3. fu is not a function
  4. fu is not defined
點我看解答(請認真思考後再看解答)

答案是:「3」

在此因為函式所傳入的是一個字串,也就是「'小明'」,因此在這邊並沒有辦法針對字串呼叫並執行。

當若無法理解時,可以試著將傳入的參數 fn 看成這樣子

1
2
3
4
5
function a ('小明') {
'小明'();
};

a('小明');

第二題

那些是表達式與陳述式?

1
2
3
4
5
6
7
8
9
10
11
12
13
function a() {
console.log('hexSchool a');
};

function b() {
return 'hexSchool b';
}

var c = function () {
console.log('hexSchool c');
}

var d;
  1. a-陳述式,b-陳述式,c-表達式,d-陳述式
  2. a-陳述式,b-表達式,c-陳述式,d-表達式
  3. a-表達式,b-陳述式,c-陳述式,d-陳述式
  4. a-陳述式,b-表達式,c-陳述式,d-陳述式
點我看解答(請認真思考後再看解答)

答案是:「1」

在此 ab 以及 d 都是陳述式而表達式是 c 而已,最主要是匿名表達函式必須有一個變數接收,雖然 breturn 但這並不代表這是一個陳述式,在此是因為它是宣告一個陳述式。

第三題

請問以下立即函式會出現什麼訊息?

1
2
3
4
5
6
7
(function () {
console.log('六角學院 A');
}());

(function () {
console.log('六角學院 B');
});
  1. 六角學院 A / 六角學院 B
  2. 六角學院 A / (){ console.log('六角學院 B'); }
  3. 六角學院 A / (...)is not defined
  4. 六角學院 A / undefined
點我看解答(請認真思考後再看解答)

答案是:「2」

首先在此 () 包覆的內容會回傳內容,因此 () 是一個表達式,因此第二個才會回傳函式本身。

因此你若這樣子寫

1
2
3
(
console.log
)

你會發現將會回傳一個 function log 唷~

第四題

請問以下 closure 將會回傳 casper 錢包內目前有多少?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function myMoney(storage) {
var money = storage || 10000;
return function(price) {
return {
nowMoney: function () {
return console.log('目前錢包:' + money);
},
count: function (price) {
if(money < price) return console.log('餘額不足');
if (!money <= 0) {
return money = money - price;
}
return console.log('餘額扣除失敗');
}
}
}
}

var casper = myMoney(10000);

casper().count(8000);
casper().nowMoney();
  1. 餘額扣除失敗
  2. 餘額不足
  3. 目前錢包: 2000
  4. 目前錢包: 10000
點我看解答(請認真思考後再看解答)

答案是:「3」

首先我們可以先回想一下閉包的重點,閉包最主要重點在於變數不會被記憶體釋放掉,因此程式碼並不用太認真閱讀,只需要尋找這幾個地方,也就是初始化紀錄變數的地方

1
var money = storage || 10000;

這邊我們可以知道如果沒有傳入變數時,預設金額會是 10000

接下來我們呼叫了閉包然後傳入的金額並儲存到變數內

1
var casper = myMoney(10000);

所以目前閉包內變數是 var money = 10000;

接下來我們呼叫了閉包內的方法 count 扣掉了 8000 最後再輸出目前金額,所以目前金額是 2000

第五題

請問 this 將會出現什麼答案?

1
2
3
4
5
6
7
8
9
10
var name = '小明';
var obj = {
x: function () {
name = '小王';
console.log(this.name);
},
y: '2'
}

obj.x();
  1. undefined
  2. 小明
  3. 小王
  4. 2
點我看解答(請認真思考後再看解答)

答案是:「1」

這題在前面章節其實已經有類似的考題,所以就不再次解釋哩。

第六題

請問 this 將會出現什麼答案?

1
2
3
4
5
6
7
8
9
10
11
var name = '小明';
var obj = {
x: function () {
name = '小王';
console.log(this.name);
},
y: '2',
name: '小美',
}

obj.x();
  1. undefined
  2. 小明
  3. 小王
  4. 小美
點我看解答(請認真思考後再看解答)

答案是:「4」

這題與上方雷同,前面章節已介紹過,因此不再次解釋。

第七題

請問 this 將會出現什麼答案?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var name = 'casper';
function sayHi() {
var name = '小王';
setTimeout(function(){
console.log(this.name);
}, 2000);
}

var obj = {
name: '小明',
callName: sayHi,
};

obj.callName();
  1. casper
  2. 小明
  3. undefined
  4. 小王
點我看解答(請認真思考後再看解答)

答案是:「1」

這一題主要考的是 sample call,因此答案就會是 casper

第八題

請問 this 將會出現什麼答案?

1
2
3
4
5
6
7
function fu(a) {
a = '小明';
}
fu.a = '小美';
fu('大明');

console.log(this.fu.a);
  1. 小明
  2. 小美
  3. 大明
  4. undefined
點我看解答(請認真思考後再看解答)

答案是:「2」

在此其實考的觀念是「函式也是物件的一個」,因此 fu.a = '小美'; 意思是我在這個函式下新增一個屬性叫做 a 並賦予值是 '小美',因此 console.log(this.fu.a);'小美'

而在此 this 呢?由於我們是直接呼叫,也就是簡易呼叫,因此指向絕對會是 window 哩。

第九題

請問 this 將會出現什麼答案?

1
2
3
4
5
6
7
8
9
10
var person = {
fistname: '小明',
};

function name (fistname) {
console.log('哈囉,' + this.fistname);
}

var sayHi = name.bind(person);
sayHi('小美');
  1. 哈囉,小明
  2. 哈囉,小美
  3. 哈囉,undefined
  4. sayHi is not defined
點我看解答(請認真思考後再看解答)

答案是:「1」

在此考的是使用 bind 指定 this 指向,除此之外 bind 並不會立刻執行,儘管看是我們有傳入一個參數叫做 '小美',但是因為有指向 this,而在此又因為是簡易呼叫,因此會指向到 '小明'

第十題

請問以下答案將會出現什麼?

1
2
3
4
5
6
7
8
9
10
11
12
13
function a(a) {
a();
}

function b(b) {
b();
}

function c(c){
console.log('casper');
}

a(b(c));
  1. casper / undefined
  2. casper / c is not defined
  3. casper / a is not a function
  4. undefined / b is not a function
點我看解答(請認真思考後再看解答)

答案是:「3」

這一題算是考了一點函式的執行順序以及有無回傳的觀念,所以在理解上相對難度高很多。

在看程式碼之前,我們可以先看到 MDN 的優先性與相依性這一篇說明

接下來看到 「Function Call」 這一段

Function Call

可以看到 Function Call 是從左邊開始執行

但是答案卻是「casper / a is not a function」這是為什麼呢?原因在於我們並不是在同一行內(1 < 2 < 3)同時呼叫,而是 Function Call 內又一個 Function Call,因此內層的 Function Call 會優先執行,所以 b(c) 被優先執行完畢,那麼當它執行完畢之後,我們並沒有將 function b 的參數回傳,所以函式所傳入的參數就不存在那麼就會變成 undefined 呼叫,你不信?我們可以這樣子驗證

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function a(a) {
console.log(a); // undefined
a();
}

function b(b) {
b();
}

function c(c){
console.log('casper');
}

a(b(c));

你應該會看到 casper 然後接著 undefined,所以我們的 a(); 其實是在針對 undefined 呼叫,那麼就會出現錯誤哩。

那這邊你可能會希望說,你也希望 a 也可以呼叫,那麼該怎麼改程式碼呢?其實只要補上 return b 就可以囉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function a(a) {
a();
}

function b(b) {
b();
return b; // 補上這一行
}

function c(c){
console.log('casper');
}

a(b(c));

這樣就可以呼叫哩~

參考文獻