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