摘要:廖雪峰的教程學習筆記變量作用域不能聲明塊級的變量,的函數內變量聲明會被提升至函數體開頭則用來解決這個塊級變量聲明,于引入。普通函數一般將賦值為。高階函數輸出結果是。箭頭函數新引入的相當于如下的匿名函數其中為參數。
廖雪峰的JavaScript教程學習筆記 1. 變量作用域
var 不能聲明塊級的變量,js的函數內變量聲明會被提升至函數體開頭
let 則用來解決這個塊級變量聲明,于ES6引入。
const用于聲明常量,也是ES6引入。
全局變量會被默認綁定到window,不同JS文件如果定義了相同的名稱的全局變量或者頂級函數,那么就會導致沖突。因此,解決方法就是把自己的全局變量綁定到一個全局變量中,類似于Java中的class,個人感覺。
3.this 關鍵字var xiaoming = { name: "小明", birth: 1990, age: function () { var y = new Date().getFullYear(); return y - this.birth; } }; xiaoming.age; // function xiaoming.age() xiaoming.age(); // 今年調用是25,明年調用就變成26了
因為xiaoming是個對象,所以方法內部的this就是指當前xiaoming這個對象,和java對象內部使用的this是一個意思。但是如果在方法內不又定義了方法,并在這個內部方法里引用this,那么這個this將報錯,undefined或者window。如果從java角度看的話,有點像是內部類里使用this因而出錯。 但也可以在內部方法的外層,捕獲this對象,比如賦值給that。
4. apply 和 call每個函數都自帶apply和call方法,其中apply接受兩個參數(object, arguments[]), 即傳入對象本身和參數數組,這樣就方法體內的this就會自動指向object,從而避免this亂指。
call方法與apply具有同樣的功能,第一個也是object自己,之后是參數列表,非Array。
普通函數一般將obejct賦值為null。
比如
Math.max.call(null, 3,4,4,5,6,6,67,8,9); Math.max.apply(null, [3,4,4,5,6,6,67,8,9]);5. 裝飾器
javascript所有的對象都是動態,即使是內置的函數,也可以重新指向新的函數。
如window上有個全局函數parseInt()函數,需要統計parseInt被調用次數。
var count = 0; var oldParseInt = parseInt; // 保存原函數 window.parseInt = function () { count += 1; // arguments是函數的參數數組 return oldParseInt.apply(null, arguments); // 調用原函數 }; // 測試: parseInt("10"); parseInt("20"); parseInt("30"); count; // 3
可以看出來JavaScript如此輕易就實現了裝飾器,java哭暈在廁所。
6. 高階函數定義:高階函數英文叫Higher-order function。
JavaScript的函數其實都指向某個變量。既然變量可以指向函數,函數的參數能接收變量,那么一個函數就可以接收另一個函數作為參數,這種函數就稱之為高階函數。這個厲害了,WOW。
里面也涉及到一個javascript的函數的參數是可以傳入多個或不傳的原理,所以方法體內才可以直接對傳入變量輸入參數,并且個數不限制。直接show me the fucking source code。
function add(x, y, f){ return f(x) + f(y); } var f = Math.abs; add(6, -3, f); // 輸出97. 高階函數map/reduce
666啊,這個map/reduce不是大數據用的么?居然是js的高階函數啊,看起來好吊啊,真是吊打java了。
網上找了一段解釋:
array.map(callback[, thisArg]);map 方法會給原數組中的每個元素都按順序調用一次 callback 函數。callback 每次執行后的返回值組合起來形成一個新數組。 callback 函數只會在有值的索引上被調用;那些從來沒被賦過值或者使用 delete 刪除的索引則不會被調用。
callback 函數會被自動傳入三個參數:數組元素,元素索引,原數組本身。
如果 thisArg 參數有值,則每次 callback 函數被調用的時候,this 都會指向 thisArg 參數上的這個對象。如果省略了 thisArg 參數,或者賦值為 null 或 undefined,則 this 指向全局對象 。
如對每個元素進行平方運算。
var pow = function(x){ return x*x; } var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; arr.map(pow);
輸出結果是[1, 4, 9, 16, 25, 36, 49, 64, 81]。
所以結合上面的解釋就是map對數組arr的每個元素調用一次callback即pow()函數。由于map會給callback傳入三個參數,而pow只取了第一個參數,即數組元素,所以結果是對每個元素平方,然后組成成新的數組。
我們可以試著修改pow,去把傳入到callback的第二個參數也使用上,那么我們來試試給給每個元素平方后加上他的索引值。
var pow = function(x){ return x*x+arguments[1]; } var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; arr.map(pow);
輸出結果為[1, 5, 11, 19, 29, 41, 55, 71, 89]。
更為具體的map定義可以看MSDN的解釋。
接下來看看reduce函數。同樣作為array的方法,reduce是對數組的每一個元素與其下一個元素調用callback一次方法,并將callback的結果作為下一次的參數與下一個元素再次調用callback方法,進行累積運算。有點繞,看數學公式可能更好理解
[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
所以我們來進行一個求和,計算1到100和運算。
var arr = []; for(var i = 1; i <= 100; i++){ arr[i-1] = i; } arr.reduce(function (x, y){ return x+y; });
輸出結果為5050。
再來看看具體reduce定義
arr.reduce(callback[,initialValue])
initialValue作為reduce方法的可選參數,callback接收4個參數, accumulator 是累積值,如果reduce方法設定了initialValue,那么accumulator的初始值就是initialValue。
accumulator
currentValue
currentIndex
array
所以我們可以繼續嘗試設定初始的方式
var arr = []; for(var i = 1; i <= 100; i++){ arr[i-1] = i; } arr.reduce(function (x, y){ return x+y; }, 100);
我們將初始值設為100,那么輸出結果是5150。
測試題
不要使用JavaScript內置的parseInt()函數,利用map和reduce操作實現一個string2int()函數:
function string2ints(s){
return s.split("").map(function(x){ return x*1}).reduce(function(x, y){ return x*10+y*1; });
}
請把用戶輸入的不規范的英文名字,變為首字母大寫,其他小寫的規范名字。輸入:["adam", "LISA", "barT"],輸出:["Adam", "Lisa", "Bart"]。
// comment on this var arr = ["LINda", "adam", "barT"]; arr.map(function(x){ return x.toLowerCase();}).map(function(x){ return x[0].toUpperCase()+x.slice(1); });
小明的疑惑在與沒搞懂parseInt的接受的參數,因為map的callback默認是會傳入三個參數,而parseInt的參數有兩個parseInt(string, radix);那么此時parseInt自動忽略傳入的第三個參數array,而傳入了(element, index)。索引改變了進制,因而得到錯誤的結果。
這個感覺是個坑,還不清楚IDE是否會提示函數或者方法的參數為啥。
語法:var new_array = arr.filter(callback[, thisArg])
filter也是一個常用的操作,它用于把Array的某些元素過濾掉,然后返回剩下的元素。與map相同的是,它也接受一個函數callback,然后對每個元素調用函數進行處理,不同的地方在于,函數需要返回true或false,用戶決定是保留該元素還是刪除該元素,最后生成一個新的數組,如其名字所決定的一樣。thisAgrs不用解釋。
其中callback同樣接收3個參數element,index,array。
簡單的做個去重操作和過濾掉奇數。
var arr = [1,2,3,4,4,4,5,5,5,6,6,7,7,8,8,9,9,9]; arr.filter(function(x){return x % 2 === 0;}) .filter(function(element, index, self){ return self.indexOf(element) === index;} );
self.index(element)只會返回找到的第一個元素的index,因此后續的index就不再相等了。
在做一個找出1-100以內所有的質數或者說素數。
質數或素數定義
質數大于等于2 不能被它本身和1以外的數整除
做法:在一般領域,對正整數n,如果用2到sqrt(n)之間的所有整數去除,均無法整除,則n為質數。
代碼:
function getPrimes(arr){ return arr.filter(function(x){ if(x <= 3) return x>1; // 大于等于2才可以為質數,所以1除外 // 2到sqrt(n)之間均無法整除,即只要有一個可以整除即非質數。 var end = Math.round(Math.sqrt(x)); for(let i=2; i <= end; i++){ if(x % i === 0) return false; } return true; }); }9.高階函數sort
[1, 2,3,10,24].sort();
輸出結果是[1, 10, 2, 24, 3]。javascript或默認將數組里數字轉換成string去比較,那么根據ASCII嘛,自然是1要比2小,所以10就在2的前面。
But, 高階函數嘛,那么自然sort也是可以接受函數來進行修改比較算法的,類似于要實現Java里的comparable接口,規則也是類似的,若x < y, 則返回-1,表示小于;若x === y, 返回0;若x > y,則返回1。理論上,并不要定義為1或者-1,只要用正數表示大于,負數表示小于就好了。所以你可以直接使用x-y;
那就數字排個序好了。
arr = [12343,5435,6,7,2,3,77,88,322]; arr.sort(function(x, y){ return x-y; });
10.閉包Caution:這個sort方法會將排序結果直接作用在數組本身上,即會修改arr。
高階函數除了可以接受函數作為參數外,還可以把函數作為結果值返回。
比如返回求和的函數。
function lazy_sum(arr){ var sum = function(){ return arr.reduce(function(x, y){ return x+y; }); return sum; } // 使用時 var f = lazy_sum([1,3,2,5]); f(); var f1 = lazy_sum([1,3,2,5]); f === f1; // result is false.
由于返回的是個函數,即使傳入的參數相等,也相當于是返回了不同的函數對象。
返回閉包時牢記的一點就是:返回函數不要引用任何循環變量,或者后續會發生變化的變量。
這個例子返回的函數引用了局部變量, 如果局部變量后續會變化,那么最好是再創建一個函數,綁定局部變量作為參數。
創建匿名函數并立刻執行.
(function (x) { return x * x }) (3);
其中function (x) { return x * x }是匿名函數,需要使用括號括起來才可以立刻執行,不然會報語法錯誤。
使用閉關封裝一個私有變量private。
function create_counter(initial){ var x = initial || 0; return { inc:function(){ x += 1; return x; } } }
create_counter()返回了一個匿名對象,這個對象有個屬性inc,而這個inc的值又是一個函數。那么就可以獲取這個匿名對象,然后調用函數inc()即可實現對private的x加1.
縮減參數列表的用法
function make_pow(n){ return function(x){ return Math.pow(x,n); } } var pow2 = make_pow(2);// 返回一個Math.pow(x, 2)的函數。 var pow3 = make_pow(3);// 返回一個Math.pow(x, 3)的函數。
pow2 和 pow3就只需要接收一個參數,即可實現power的操作。
底下的Lambda表達式加法沒能理解呀。
11.箭頭函數ES6 新引入的
x => x * x
相當于如下的匿名函數,其中x為參數。
function (x){ return x*x; }
如果有多個參數需要使用括號括起來,如(x,y) => x+y;。
用法呢和匿名函數也差不多,比如:
var pow2 = x=> x*x; pow2(2); // 4 // 創建匿名函數并執行 (x => x*x)(2); // 4
還有一種包含多條語句的,需要使用{}將其包起來。如:
(x, y) => { if(x>y){ return x-y;} else{ return y-x;} }
還有類似于()=>3.14的寫法,雖然看起來沒啥卵用。
可變參數寫法,就是參數變了一下
(x, y, ...rest) =>{ var sum= x =y; for(var x of arguments){ sum += x; } return sum; }
廖老師說x => { foo: x }這樣寫會語義錯誤,然而并沒有。但是確實沒能夠被正確解析,所以當返回匿名對象的時候,使用()將其包起來,如x => ({ foo: x })。
需要注意的是箭頭函數內部的this是詞法作用域,由上下文確定。箭頭函數完全修復了this的指向,this總是指向詞法作用域,也就是外層調用者obj。那么在第4節里說的每個函數都自帶apply和call方法,他們的第一個參數object就都不在有用,因為箭頭函數會自動綁定外層調用者obj。
12. generatorES6新引入的數據類型,看上去像是一個函數,但是可以返回多次。
與函數定義不同的是,使用function*來定義一個generator,除了使用return退出函數之后,還可以使用yield交出控制權,這時并沒有退出整個函數,使用next時,就會從當前yield處往下執行。
以斐波那契數列為例:[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]
普通的使用數組來保存結果的斐波那契數列生成方法
function fib(max){ var t, a = 0, b = 1, arr = [0, 1]; while (arr.length < max){ t = a + b; a = b; b = t; arr.push(t); } return arr; }
以generator生成器生成斐波那契數列的方法。
function* fib2(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 = fib2(5); undefined > f.next(); // 輸出0返回。 Object {value: 0, done: false} > f.next(); Object {value: 1, done: false} > f.next(); Object {value: 1, done: false} > f.next(); Object {value: 2, done: false} > f.next(); Object {value: 3, done: true} > f.next(); Object {value: undefined, done: true}
可以看到每次調用next,都會促使整段代碼執行到下一個yield,然后輸出一個匿名對象{value:xx, done:true/false} 其中xx是yield的返回值,done是表明此時是否生成結束,即是否執行到return。
還有一種使用方式,就是for...of,無需判斷是否執行完畢。
for (var x of fib(5)) { console.log(x); // 依次輸出0, 1, 1, 2, 3 }
But這個generator有啥卵用呢?我暫時想起來一個狀態轉換的,即每次調用都會切換到下一個狀態,直到切換完成,像Android中的StateMachine一樣。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91292.html
摘要:網上有很多前端的學習路徑文章,大多是知識點羅列為主或是資料的匯總,數據量讓新人望而卻步。天了解一個前端框架。也可以關注微信公眾號曉舟報告,發送獲取資料,就能收到下載密碼,網盤地址在最下方,獲取教程和案例的資料。 前言 好的學習方法可以事半功倍,好的學習路徑可以指明前進方向。這篇文章不僅要寫學習路徑,還要寫學習方法,還要發資料,干貨滿滿,準備接招。 網上有很多前端的學習路徑文章,大多是知...
摘要:本題目的考察點在于函數的格式輸出規則。方法改變隨機數生成器的種子,可以在調用其他隨機模塊函數之前調用此函數。參數改變隨機數生成器的種子。返回一個至區間包含和的整數。 ...
摘要:作者簡介是推出的一個天挑戰。完整指南在從零到壹全棧部落。通過時分秒對一圈度,進行映射,確定每一個指針所需旋轉的角度。此前的代碼中,每秒都會重新一個對象,用來計算角度值,但如果讓這個角度值一直保持增長,也就不會出現逆時針回旋的問題了。 Day02 - JavaScript + CSS Clock 作者:?liyuechun 簡介:JavaScript30 是 Wes Bos 推出的一個...
閱讀 876·2021-11-15 11:37
閱讀 3611·2021-11-11 16:55
閱讀 3276·2021-11-11 11:01
閱讀 1005·2019-08-30 15:43
閱讀 2751·2019-08-30 14:12
閱讀 686·2019-08-30 12:58
閱讀 3394·2019-08-29 15:19
閱讀 2033·2019-08-29 13:59