【Q】網(wǎng)易微專業(yè)-JS16 函數(shù)進階

Q1:(function(){}()最后這個()有什么意義跋涣?必須有這個()才是閉包?铜靶?

var sum = (function(){
            var add=function(i,j){
                return i+j;
            }
            return function(i,j){
                add(i,j);
            }
        })()//(function(){}()最后這個()有什么意義玄柠?必須有這個()才是閉包?敏弃?)```

1.函數(shù)定義
注:函數(shù)實例化很少用
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/316258-e767e47bbb2978f6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

Q1:函數(shù)聲明在函數(shù)定義前能被調(diào)用,為什么噪馏?
Q2:函數(shù)表達式和實例化在函數(shù)定義前不能被調(diào)用麦到,為什么绿饵?

2.代碼執(zhí)行過程
?代碼執(zhí)行前先預(yù)解析(將變量、變量聲明瓶颠、函數(shù)定義 提前處理)拟赊,然后單步執(zhí)行JS代碼。
?函數(shù)聲明被前置到頂部執(zhí)行步清。
?當(dāng)用函數(shù)聲明重復(fù)定義一個函數(shù)時要门,只有最后一次定義有效。
![](http://upload-images.jianshu.io/upload_images/316258-1e45e15dff2f2a4f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![](http://upload-images.jianshu.io/upload_images/316258-a683a60084e30007.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![思考題](http://upload-images.jianshu.io/upload_images/316258-24271750ef0f9e5c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
>A:執(zhí)行結(jié)果:
函數(shù)聲明:101
函數(shù)表達式:11
函數(shù)表達式:11
——

var add1; //最頂部的變量聲明
function add1(i) {
console.log("函數(shù)聲明:"+(i+1));
}
function add1(i) {
console.log("函數(shù)聲明:"+(i+100));
}
add1(1); //當(dāng)執(zhí)行這句時廓啊,上面兩個相同的函數(shù)聲明欢搜,后面的覆蓋了前面的聲明,因此按照第二個函數(shù)的結(jié)果輸出 為101
add1 = function (i) { //代碼所在位置的變量賦值
console.log("函數(shù)表達式:"+(i+10));
};
add1(1); //此時的add1指向了最后定義的匿名函數(shù)了谴轮,因此執(zhí)行結(jié)果為 11
add1(1); //沒有其他代碼改變add1的指向炒瘟,因此add1(1)的執(zhí)行結(jié)果還是11```

3.函數(shù)定義之間的區(qū)別


Paste_Image.png
Paste_Image.png

4.函數(shù)調(diào)用4種模式
注:自定義構(gòu)造函數(shù)建議首字母大寫,便于相互理解


函數(shù)調(diào)用模式

⑴方法調(diào)用模式

 var myNumber = {
   value: 1,
   add: function(i){
    console.log(this);
    this.value += i;
   }
 }
 myNumber.add(1);```
⑵apply調(diào)用模式
apply:Function構(gòu)造函數(shù)原型對象上的一個方法第步。構(gòu)造函數(shù)的原型對象會被它創(chuàng)建的對象的原型鏈引用疮装,而任何函數(shù)都是Function構(gòu)造函數(shù)的實例,所以任何函數(shù)都可以直接調(diào)用apply方法粘都。
apply功能:函數(shù)借用廓推。將函數(shù)借用給一個對象,幫助它實現(xiàn)函數(shù)所定義的邏輯翩隧。
![apply調(diào)用模式樊展,apply將p.move方法借用給circle這個對象](http://upload-images.jianshu.io/upload_images/316258-86b11eda2f4e8712.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

⑶函數(shù)調(diào)用模式的區(qū)別
函數(shù)執(zhí)行時,JS引擎在函數(shù)本地作用域自動添加this堆生、arguments兩個臨時變量专缠,函數(shù)調(diào)用模式本質(zhì)區(qū)別就體現(xiàn)在this變量的指向上。
![區(qū)別](http://upload-images.jianshu.io/upload_images/316258-e3a9cd3bf2c23447.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![arguments作用:用于獲取函數(shù)實參
arguments[index]實參
arguments.length實參個數(shù)](http://upload-images.jianshu.io/upload_images/316258-2c25fa02ba161f1c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

>![思考題](http://upload-images.jianshu.io/upload_images/316258-caf17ed74d0f0d0e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

>1.this指向Window全局變量
2.不能
3.實現(xiàn)方法

//方法一:可以把helper調(diào)整為方法函數(shù)淑仆,這樣helper就可以正確引用myNumber為this了
var myNumber = {
value:1,
helper:function(i) {
console.log(this);
this.value +=i;
},
add: function(i) {
this.helper(i);
}
}
myNumber.add(1);
//方法二:使用閉包
var myNumber = {
value: 1,
add: function(i){
var thisnew = this;
// 構(gòu)建閉包
var helper = function(i){
console.log(thisnew);
thisnew.value += i;
}
helper(i);
}
}
//方法三:使用apply(call)調(diào)用模式涝婉,將當(dāng)前helper方法借用給myNumber對象使用,這樣this指向的就是myNumber對象
var myNumber = {
value: 1,
add: function(i){
var helper = function(i){
console.log(this);
this.value += i;
}
// myNumber對象借用helper方法蔗怠,helper中的this將指向myNumber對象
helper.apply(myNumber,[i]); //apply方法
helper.call(myNumber,i); //call方法
}
}
//方法4墩弯,最笨的一種,針對這個題目只要不用this.value改成myNumber.value就可以了
var myNumber = {
value: 1,
add: function(i){
var helper = function(i);
console.log(this);
myNumber.value += i;
}
helper(i);
}
}
myNumber.add(1);```

5.函數(shù)傳參
按值傳遞call by value:一個外部變量傳遞給一個函數(shù)時寞射,函數(shù)實參獲取的時這個外部變量的副本最住,在函數(shù)內(nèi)部對實參修改,不會反映在外部變量怠惶。
引用傳遞:一個外部變量傳遞給一個函數(shù)時,函數(shù)實參實際上是這個外部變量的引用轧粟,在函數(shù)內(nèi)部對實參修改策治,都會反應(yīng)到外部變量脓魏。


函數(shù)傳參
共享傳遞中,obj實際上獲得的是count地址的一個副本通惫,此時obj和count指向的是同一個對象茂翔,對這個對象屬性的修改都會反映在obj和count上 而在函數(shù)內(nèi)部將obj指向另一個對象時,并不會影響count
傳參總結(jié)

6.閉包Closure
⑴函數(shù)內(nèi)部定義的子函數(shù)用到了父函數(shù)變量所形成的特定的作用域履腋。

珊燎??⑵閉包有哪些功能遵湖?

Paste_Image.png

基于js執(zhí)行性能考慮悔政,被頻繁調(diào)用的函數(shù)內(nèi)部定義和調(diào)用的幫助函數(shù),如果不需要保存狀態(tài)延旧,應(yīng)該將這些幫助函數(shù)保存到閉包作用域谋国。

①閉包使用舉例1

將字符串中的一些特定字符按順序用數(shù)組中的元素替換,例如:
var arr = ['c','f','h','o'];
var str = 'ab4de8g4ijklmn7';
替換后 str == 'abcdefghijklmno';

 /*var arr = ['c','f','h','o'];
 var str = 'ab4de8g4ijklmn1';
 console.log(str);

 var func = (function(){
 // count變量會保存在閉包作用域內(nèi)迁沫,表示func被調(diào)用次數(shù)(即正在替換第幾個字符)
   var count = 0; 
   return function(){
     return arr[count++]; 
   }
 })();

 str = str.replace(/\d/g, func)
 console.log(str);```

②閉包使用舉例2 -- 封裝
1.暴露type類型和start, stop, getStatus方法
2.隱藏status芦瘾,light對象狀態(tài)

var Car = function(type){
var status = "stop",
light = "off";
return {
type: type,
start: function(){
status = "driving";
light = "on";
},
stop: function(){
status = "stop";
light = "off";
},
getStatus: function(){
console.log(type + " is " + status + " with light " + light);
}
}
}

var audi = new Car("audi");
audi.start();
audi.getStatus();
audi.stop();
audi.getStatus();```

③閉包使用舉例3 -- 性能優(yōu)化1
減少函數(shù)定義時間和內(nèi)存消耗

// 不使用閉包
function sum(i, j) {
  var add = function(i, j){
    return i+j;
  }
  return add(i, j)
}
var startTime = new Date();
for(var i = 0; i< 1000000; i++) {
  sum(1,1);
}
var endTime = new Date();
console.log(endTime - startTime);

// // // 使用閉包
var sum = (function() {
  var add = function(i, j){
    return i+j;
  }
  return function(i,j) {
    add(i, j);
  }
})()
var startTime = new Date();
for(var i = 0; i< 1000000; i++) {
  sum(1,1);
}
var endTime = new Date();
console.log(endTime - startTime);```

閉包使用舉例3 -- 性能優(yōu)化2
普通遞歸函數(shù)跟使用閉包記錄調(diào)用返回結(jié)果的遞歸函數(shù)調(diào)用次數(shù)對比

// // 普通遞歸函數(shù)
// var factorial = (function(){
// var count = 0;
// var fac = function(i){
// count++;
// if (i==0) {
// console.log('調(diào)用次數(shù):' + count);
// return 1;
// }
// return i*factorial(i-1);
// }
// return fac;
// })();
// for(var i=0;i<=10;i++){
// console.log(factorial(i));
// }

// // 使用閉包記錄調(diào)用返回結(jié)果的遞歸函數(shù) -- 記憶函數(shù)
var factorial = (function(){
var memo = [1];
var count = 0;
var fac = function(i){
count++;
var result = memo[i];
if(typeof result === 'number'){
console.log('調(diào)用次數(shù):' + count);
return result;
}
result = i*fac(i-1);
memo[i] = result;
return result;
}
return fac;
})();
for(var i=0;i<=10;i++){
console.log(factorial(i));
}```

7.first-class function:JS中函數(shù)可以當(dāng)做普通變量來使用

Paste_Image.png

8.Function.prototype.bind 所有函數(shù)都可以調(diào)用bind方法
bind返回的是函數(shù)的引用。

9集畅、函數(shù)柯里化近弟??
函數(shù)柯里化通常是指把接受多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)(最初函數(shù)的第一個參數(shù))的并且返回一個接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)挺智。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末祷愉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子逃贝,更是在濱河造成了極大的恐慌谣辞,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沐扳,死亡現(xiàn)場離奇詭異泥从,居然都是意外死亡,警方通過查閱死者的電腦和手機沪摄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進店門躯嫉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人杨拐,你說我怎么就攤上這事祈餐。” “怎么了哄陶?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵帆阳,是天一觀的道長。 經(jīng)常有香客問我屋吨,道長蜒谤,這世上最難降的妖魔是什么山宾? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮鳍徽,結(jié)果婚禮上资锰,老公的妹妹穿的比我還像新娘。我一直安慰自己阶祭,他們只是感情好绷杜,可當(dāng)我...
    茶點故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著濒募,像睡著了一般鞭盟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上萨咳,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天懊缺,我揣著相機與錄音,去河邊找鬼培他。 笑死鹃两,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的舀凛。 我是一名探鬼主播俊扳,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼猛遍!你這毒婦竟也來了馋记?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤懊烤,失蹤者是張志新(化名)和其女友劉穎梯醒,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腌紧,經(jīng)...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡茸习,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了壁肋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片号胚。...
    茶點故事閱讀 40,928評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖浸遗,靈堂內(nèi)的尸體忽然破棺而出猫胁,到底是詐尸還是另有隱情,我是刑警寧澤跛锌,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布弃秆,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏菠赚。R本人自食惡果不足惜盼樟,卻給世界環(huán)境...
    茶點故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锈至。 院中可真熱鬧,春花似錦译秦、人聲如沸峡捡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽们拙。三九已至,卻和暖如春阁吝,著一層夾襖步出監(jiān)牢的瞬間砚婆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工突勇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留装盯,地道東北人。 一個月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓甲馋,卻偏偏與公主長得像埂奈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子定躏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,937評論 2 361

推薦閱讀更多精彩內(nèi)容