sort() | 閉包 | 箭頭函數(shù) | Generator函數(shù)

概述.png

廖雪峰老師----JavaScript教程

一.sort()

  • 排序的核心荔燎?比較兩個(gè)元素的大小

  • 問題:

[1,10,5,45].sort();
//(4) [1, 10, 45, 5]

因?yàn)椋篈rray的sort()方法默認(rèn)把所有元素先轉(zhuǎn)換為String再排序病线,同時(shí)4的ASCll碼比5小皱蹦。

  • 解決
//常規(guī)方式
var arr = [1,10,45,5];
arr.sort(function(x,y){
    if(x > y){
        return 1;
    }
    if(x < y){
        return -1;
    }
    return 0;
});
//(4) [1, 5, 10, 45]
//優(yōu)雅的方式
var arr = [1,10,45,5];
arr.sort(function(a,b){
    return a-b;
});
//(4) [1, 5, 10, 45]
sort()
sort()數(shù)值排序
  • sort()方法會(huì)直接修改原數(shù)組Array,同時(shí)沒有"另起爐灶"---copy,返回的結(jié)果仍然是當(dāng)前Array。
var a1 = ['b','a','c'];
var a2 = a1.sort();
console.log(a1);//["a", "b", "c"]
console.log(a2);//["a", "b", "c"]


二. 閉包

1. 函數(shù)作為返回值

function parent(arr){
    var child = function(){
        return arr.reduce(function(a,b){
            return a+b;
        });
    }
    return child;
}
var f = parent([1,2,3,4,5]);
f();//15
  • More:該子函數(shù)可以引用父函數(shù)中的參數(shù)和局部變量北秽;當(dāng)從父函數(shù)中返回子函數(shù)時(shí),相關(guān)的參數(shù)和變量仍保存在返回的子函數(shù)內(nèi)最筒。

  • 注意:當(dāng)我們調(diào)用父函數(shù)時(shí)贺氓,每次調(diào)用都會(huì)返回一個(gè)新的函數(shù),即使傳入相同的參數(shù):

var f1 = parent([1,2,3,4,5]);
var f2 = parent([1,2,3,4,5]);
f1 === f2;//false

2. 返回的函數(shù)并沒有立刻執(zhí)行

  • 什么意思床蜘?
function count(){
    var arr = [];
    for(var i = 1;i <=3;i++){
        arr.push(function(){
            return i*i;
        });
    }
    return arr;
}
var result = count();
var f1 = result[0];
var f2 = result[1];
var f3 = result[2];
console.log(f1());//16
console.log(f2());//16
console.log(f3());//16
  • 變量result是一個(gè)指向函數(shù)count執(zhí)行結(jié)果arr的引用掠归,該數(shù)組中包含了三個(gè)函數(shù):
? (){
   return i*i;
}
  • 這三個(gè)函數(shù)都引用了父函數(shù)count中的局部變量 i,但這三個(gè)返回的子函數(shù)并沒有立即執(zhí)行悄泥。當(dāng)這三個(gè)函數(shù)都返回時(shí),它們所引用的變量i已經(jīng)變成了4肤粱,所以三次結(jié)果均為16弹囚。

  • 返回閉包時(shí)要牢記一點(diǎn):返回的函數(shù)不要引用任何循環(huán)變量,或者后續(xù)會(huì)發(fā)生變化的變量领曼。

  • 這里你想要的結(jié)果是:1 4 9鸥鹉,可以用以下方法實(shí)現(xiàn):

var arr = [1,2,3];
function square(arr){
    return arr.map(function(a){
        return a*a;
    });
}
square(arr);//[1, 4, 9]
  • 如果你非要用嵌套函數(shù)的方式
//創(chuàng)建一個(gè)匿名函數(shù)并立即執(zhí)行
function count(){
    var arr = [];
    for(var i = 1;i <=3;i++){
        arr.push((function(a){
            return function(){
                return a*a;
            }
        })(i));
    }
    return arr;
}
var result = count();
var f1 = result[0];
var f2 = result[1];
var f3 = result[2];
console.log(f1());//1
console.log(f2());//4
console.log(f3());//9
//優(yōu)雅點(diǎn)的---let
function count(){
    var arr = [];
    for(let i = 1;i <=3;i++){
        arr.push(function(){
            return i*i;
        });
    }
    return arr;
}
var result = count();
var f1 = result[0];
var f2 = result[1];
var f3 = result[2];
console.log(f1());//1
console.log(f2());//4
console.log(f3());//9

3. 閉包的真正威力

  • 模擬私有變量:

  • 設(shè)計(jì)一個(gè)計(jì)數(shù)器,執(zhí)行一下庶骄,加1毁渗,而不是人工加1:

function counter(i){
    return i++;
}
counter(0);
//0
counter(1);
//1
counter(2);
//2
counter(3);
//3
//自動(dòng)化
function counter(initial){
    var x = initial || 0;//防止initial = undefined
    return {
        inc : function(){
            return x++;
        }
    };
}
var c1 = counter();
c1.inc();//0
c1.inc();//1
c1.inc();//2
c1.inc();//3

閉包就是攜帶狀態(tài)的函數(shù),并且它的狀態(tài)可以對外完全隱藏单刁。

4. 使用閉包將多參數(shù)的函數(shù)變成單參數(shù)的函數(shù)灸异。

  • 比如:x^y 可以使用Math.pow(x,y)函數(shù),但對于x^2 或x^3有點(diǎn)大材小用了羔飞,使用閉包弄個(gè)簡潔版的肺樟。
function make_pow(y){
    return function(x){
        return Math.pow(x,y);
    };
}
var pow2 = make_pow(2);
var pow3 = make_pow(3);
pow2(5);//25
pow3(3);//27


三. 箭頭函數(shù)(Arrow Function)

1.箭頭函數(shù) & 匿名函數(shù) 區(qū)別?

箭頭函數(shù)內(nèi)部的this是詞法作用域逻淌,由上下文決定么伯。

//匿名函數(shù)
var obj = {
    birth : 1996,
    getAge : function(){
        var b = this.birth;
        var fn = function(){
            return (new Date().getFullYear() - this.birth);
        }
        return fn();
    }
}
obj.getAge();//NaN
2017 - undefined;//NaN
//箭頭函數(shù)
var obj = {
    birth : 1996,
    getAge : function(){
        var fn = () => new Date().getFullYear() - this.birth;
        return fn();
    }
}
obj.getAge();//21
//由于箭頭函數(shù)中的this已綁定了詞法作用域,
//因此call()或者apply()調(diào)用箭頭函數(shù)時(shí)卡儒,傳入的第一個(gè)參數(shù)無效田柔。
var obj = {
    birth : 1996,
    getAge : function(year){
        var f = (y) => y - this.birth;//this.birth仍為1996,而非2000
        return f.call({birth: 2000},year);    
    }
}
obj.getAge(2017);//21


四.generator(生成器)

1.調(diào)用函數(shù):傳入?yún)?shù)骨望,返回結(jié)果

//常規(guī)方法
function fib(count){
    var a = 0,
        b = 1,
        temp,
        arr = [0,1];
    while(arr.length < count){
        temp = a + b;
        a = b;
        b = temp;
        arr.push(temp);
    }
    return arr;
}
fib(10);
>>>
(10) [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

阮一峰老師---Generator 函數(shù)的語法

  • 調(diào)用Generator函數(shù)硬爆,返回一個(gè)遍歷器對象,代表Generator函數(shù)的內(nèi)部指針锦募。以后摆屯,每次調(diào)用遍歷器對象的next方法,都會(huì)返回一個(gè)帶有value和done兩個(gè)屬性的對象。value屬性表示當(dāng)前的內(nèi)部狀態(tài)的值虐骑,是yield或者return后面那個(gè)表達(dá)式的值准验;done屬性是一個(gè)布爾值,表示是否遍歷結(jié)束廷没。

  • return & yield
    1.相似處:都返回緊跟在語句后面的那個(gè)表達(dá)式的值糊饱。
    2.區(qū)別:在一個(gè)函數(shù)中,只能執(zhí)行一個(gè)return語句颠黎,執(zhí)行后另锋,就結(jié)束該函數(shù)了。而每個(gè)yield表達(dá)式都能通過next()方法在該函數(shù)中執(zhí)行狭归。在一個(gè)函數(shù)中夭坪,每次遇到y(tǒng)ield語句,函數(shù)暫停執(zhí)行过椎,下一次再從該位置繼續(xù)往后執(zhí)行室梅,因此,它具有位置記憶的能力疚宇。
    3.next()方法會(huì)執(zhí)行Generator函數(shù)中的yield表達(dá)式和return語句亡鼠;但當(dāng)使用for...of時(shí),僅會(huì)執(zhí)行yield表達(dá)式敷待。
    4.開發(fā)者角度:通過next方法间涵,Generator函數(shù)依次遍歷yield表達(dá)式。
    5.Generator函數(shù)角度:依次生成了一系列的值榜揖,也就是Generator(生成器)名字的來源勾哩。

next()  & for...of
///next()
function* fib(max) {
    var
        t,
        a = 0,
        b = 1,
        n = 1;
    while (n < max) {
        yield a;
        t = a + b;
        a = b;
        b = t;
        n ++;
    }
    return a;
}
var f = fib(5);
f.next();
//{value: 0, done: false}
f.next();
//{value: 1, done: false}
f.next();
//{value: 1, done: false}
f.next();
//{value: 2, done: false}
f.next();
//{value: 3, done: true}

//for...of
function* fib(max) {
    var
        t,
        a = 0,
        b = 1,
        n = 1;
    while (n < max) {
        yield a;
        t = a + b;
        a = b;
        b = t;
        n ++;
    }
    return a;
}
for(var i of fib(5)){
    console.log(i);
}
>>>
0
1
1
2
  • 如果在普通函數(shù)中使用yield表達(dá)式,會(huì)產(chǎn)生語句錯(cuò)誤根盒。
var arr = [1, [[2, 3], 4], [5, 6]];
var flat = function* (a) {
  //普通函數(shù)
  a.forEach(function (item) {
    if (typeof item !== 'number') {
      yield* flat(item);
    } else {
      yield item;
    }
  });
};
for (var f of flat(arr)){
  console.log(f);
}
//Uncaught SyntaxError: Unexpected identifier
//解決:使用for循環(huán)替代內(nèi)部的普通函數(shù)
var arr = [1,[[2,3],4],[5,6]];
var flat = function* (a){
    var length = a.length;
    for(var i = 0;i < length;i++){
        var item = a[i];
        //將數(shù)組中的嵌套數(shù)組中的每個(gè)元素依次輸出
        if(typeof item !== 'number'){
            yield* flat(item);
        }else{
            yield item;
        }
    }
};
for(var f of flat(arr)){
    console.log(f);
}

>>>
1
2
3
4
5
6
  • yield表達(dá)式如果用在另一個(gè)表達(dá)式中钳幅,必須用圓括號括起來:
function* demo() {
  console.log('Hello' + yield); // SyntaxError
  console.log('Hello' + yield 123); // SyntaxError
}
//Uncaught SyntaxError: Unexpected identifier

function* demo() {
  console.log('Hello ' + (yield)); // OK
  console.log('Hello ' + (yield 123)); // OK
}
var f = demo();
f.next();
//{value: undefined, done: false}

f.next();
>>>
Hello undefined
{value: 123, done: false}

f.next();
>>>
Hello undefined
{value: undefined, done: true}
  • yield表達(dá)式用作函數(shù)參數(shù)或放在賦值表達(dá)式的右邊,可以不加括號
function* demo(){
    foo(yield 'a',yield 'b');
    let input = yield;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炎滞,一起剝皮案震驚了整個(gè)濱河市敢艰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌册赛,老刑警劉巖钠导,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異森瘪,居然都是意外死亡牡属,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門扼睬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逮栅,“玉大人悴势,你說我怎么就攤上這事〈敕ィ” “怎么了特纤?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長侥加。 經(jīng)常有香客問我捧存,道長,這世上最難降的妖魔是什么担败? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任毫目,我火速辦了婚禮吆录,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘剖淀。我一直安慰自己辈毯,他們只是感情好格粪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布显押。 她就那樣靜靜地躺著柳洋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪孙援。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天扇雕,我揣著相機(jī)與錄音拓售,去河邊找鬼。 笑死镶奉,一個(gè)胖子當(dāng)著我的面吹牛础淤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哨苛,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼鸽凶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了建峭?” 一聲冷哼從身側(cè)響起玻侥,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎亿蒸,沒想到半個(gè)月后凑兰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡边锁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年姑食,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片茅坛。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡音半,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情曹鸠,我是刑警寧澤煌茬,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站物延,受9級特大地震影響宣旱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叛薯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一浑吟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧耗溜,春花似錦组力、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至阿宅,卻和暖如春候衍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背洒放。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工蛉鹿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人往湿。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓妖异,卻偏偏與公主長得像,于是被迫代替她去往敵國和親领追。 傳聞我的和親對象是個(gè)殘疾皇子他膳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

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