箭頭函數(=>)具備隱式返回的特性。若是某個函數體只有單個表達式,你就能夠忽略return關鍵字:()=>foo是一個不須要參數,並且最後會返回字符串foo
的函數。
並且須要注意的是,當你想要返回一個對象字面量的時候,若是你使用了大括號,javascript會默認你想要建立一個函數體。像是{ broken:true}。若是你想要經過隱式返回來返回一個字面量對象,那你就須要在你的字面量對象外面包裹一層小括號來消除這種歧義。javascript
const noop = () => { foo: 'bar'}l console.log(noop());// undefined const createFoo = () => ({foo: 'bar'}); console.log(createFoo());// { foo: "bar"}
在第一個例子中,foo會被理解成一個標籤,而bar會被理解成一個沒有被賦值的表達式,這個函數會返回undefined.
而在createFoo()的例子中,圓括號強制讓大括號裏的內容被解釋成爲一個須要被計算的表達式,而不是一個函數體。java
先看一個函數的聲明。es6
const createUser = ({ userName, avatar}) => {}
在這一行中,大括號({})表明了對象的解構。這個函數接受一個參數(一個對象)。可是從這個單一對象中又解構出了兩個形參,userName和avatar。這些參數均可以被看成函數體做用域內的變量使用。你一樣也能夠解構一些數組:chrome
const swap = ([first, second]) => [second, first]; console.log( swap([1,2]) ); // [2,1]
你也可使用拓展運算符(...varName)來獲取數組(或者參數列表)中的其餘值,而後將這些數組元素回傳成單個元素:express
const rotate = ([first, ...rest]) => [...rest, first]; console.log( rotate([1,2,3])); // [2,3,1]
先看一個示例json
const arrToObj = ([key, value]) => ({ [key]: value }); console.log( arrToObj([ 'foo', 'bar' ]) ); // { "foo": "bar" }
在這個例子裏,arrToObj將一個包含鍵值對(也叫元組)的數組轉換成了一個對象。由於咱們不知道鍵的名稱,因此咱們須要經過計算屬性名來在對象中設置鍵值對。
這裏須要知道js中訪問對象屬性的二者方式js對象屬性中.號和中括號的區別。咱們能夠經過[]中括號去動態的設置對象屬性屬性名。數組
js中訪問對象屬性有二者方式,一個是經過點號,一個是中括號。
一、中括號的運算符能夠用字符串變量的內容做爲屬性名。點運算符不能。好比obj['string'+variable];即前者屬性名能夠是動態的。然後者須要是靜態的
二、中括號運算符能夠用純數字做爲屬性名。點運算符不能。
三、中括號運算符能夠用js的關鍵字和保留字做爲屬性名。點運算符不能。瀏覽器
//example function aa(key,value){ console.log({[key]:value}) } console.log(aa("asd","123"));// {"asd","123"}
一、將json對象轉化爲json字符串,再判斷該字符串是否爲"{}"app
var data = {}; var b = (JSON.stringify(data) === "{}") console.log(b) //true
二、for in 循環判斷函數
var obj = {}; var b = function(){ for( var key in obj) { return false; } return true; } console.log(b);// true
三、Object.getOwnPropertyNames()方法
此方法是使用Object對象的getOwnPropertyNames方法,獲取到對象中的屬性名,存到一個數組中,經過判斷數組的length來判斷對象是否爲空。
var data = {}; var arr = Object.getOwnPropertyNames(data); alert(arr.length == 0);//true
四、使用ES6的Object.keys()方法
var data = {}; var arr = Object.keys(data); console.log(arr.length === 0);//true
isNaN() 函數用來肯定一個值是否爲NaN。
當算術運算返回一個未定義的或沒法表示的值時,NaN就產生了。可是,NaN並不必定用於表示某些值超出表示範圍的狀況。將某些不能強制轉換爲數值的非數值轉換爲數值的時候,也會獲得NaN。
能夠經過isNaN去判斷一個值是否爲數字
if(isNaN(str)){ console.log("不是數字") }else{ console.log("是數字") } // isNaN的polyfill var isNaN = function(value){ var n = parseInt(value) return n !== n }
擴展:es6擴展了一個Number.isNaN的方法,傳遞的值是否爲 NaN和其類型是 Number。它是原始的全局isNaN()的更強大的版本。
isNaN的擴展。和全局函數 isNaN()相比,該方法不會強制將參數轉換成數字,只有在參數是真正的數字類型,且值爲 NaN 的時候纔會返回 true。
Number.isNaN(NaN); // true Number.isNaN(Number.NaN); // true Number.isNaN(0 / 0) // true // 下面這幾個若是使用全局的 isNaN() 時,會返回 true。 Number.isNaN("NaN"); // false,字符串 "NaN" 不會被隱式轉換成數字 NaN。 Number.isNaN(undefined); // false Number.isNaN({}); // false Number.isNaN("blabla"); // false // 下面的都返回 false Number.isNaN(true); Number.isNaN(null); Number.isNaN(37); Number.isNaN("37"); Number.isNaN("37.37"); Number.isNaN(""); Number.isNaN(" "); // polyfill Number.isNaN = Number.isNaN || function(value) { return typeof value === "number" && isNaN(value); }
localeCompare()方法返回一個數字來指示一個參考字符串是否在排序順序前面或以後或與給定字符串相同。
返回一個數字表示是否 引用字符串 在排序中位於 比較字符串 的前面,後面,或者兩者相同。
//能夠用該方法結合sort方法對字符串數組進行排序: var str="abbbbAAbcBCCccdaACBDDabcccddddaab"; str.join().sort(function(a,b){return a.localeCompare(b)})
Object.freeze()方法能夠凍結一個對象,凍結指的是不能向這個對象添加新的屬性,不能修改已有的屬性的值,不能刪除已有屬性,以及不能修改對象已有的可枚舉性、可配置性、可寫性。也就是說,這個對象永遠是不可變的。該方法返回被凍結的對象。
//examples const object1 = { property1:42 }; const object2 = Object.freeze(object1); object2.property1 = 33; // Throws an error in strict mode console.log(object2.property1); // expected output:42
注意:
一、被凍結的對象自身的全部屬性都不可能以任何方式被修改(淺凍結狀況下,若是被凍結的對象含有對象屬性,則該對象屬性不會被凍結)。任何修改嘗試都會失敗,通常會靜默或者拋出TypeError異常
二、數據屬性的值不可更改,訪問器屬性(有getter和setter)也一樣。若是一個屬性的值是個對象,在這個對象中的屬性是能夠修改的,除非它也是個凍結對象。
三、這個方法返回傳遞的對象,而不是建立一個被凍結的副本。因此不須要將返回的結果從新賦給一個新的對象,由於指向的都是同一個對象。
defineProperty方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有的屬性,並返回這個對象。
Object.defineProperty(obj, prop, descriptor)
obj 要在其上定義屬性的對象。
prop 要定義或修改的屬性的名稱。
descriptor 將被定義或修改的屬性描述符。
返回:被傳遞給函數的對象。
reduce(callback[, initialValue])方法對累加器和數組中的每一個元素(從左到右)應用一個函數,將其減小爲單個值。
const array1 = [1,2,3,4]; const reducer = (accumulator, currentValue) => accumulator + currentValue; // 1 + 2 + 3 + 4 console.log(array1.reduce(reducer)); // expected output:10 // 5 + 1 + 2 + 3 + 4 console.log(array1.reduce(reducer, 5)); // expected output:15
參數:
callback:執行數組中每一個值的函數,包含四個參數:
一、accumulator
累加器累加回調的返回值;它是上一次調用回調時返回的累積值,或initialValue
二、currentValue
數組中正則處理的元素
三、currentIndex(可選)
數組中正在處理的當前元素的索引。若是提供了initialValue,則索引號爲0,不然索引爲1。
四、array(可選)
調用reduce的數組
initialValue(可選)
用做第一個調用callback的第一個參數的值。若是沒有提供初始值,則將使用數組中的第一個元素。在沒有初始值的空數組上調用reduce將報錯。
返回值:
函數累計處理的結果。
concat()方法用於合併兩個或多個數組,此方法不會更改現有數組,而是返回一個新數組。
with語句 擴展一個語句的做用域鏈。
with (expression) { statement }
expression 將給定的表達式添加到在評估語句時做用的做用域鏈上。表達式周圍的括號是必需的。
statement
任何語句。要執行多個語句,請使用一個塊語句對這些語句進行分組
描述:javascript 查找某個未使用變量時,會經過做用域鏈來查找,做用域鏈是跟執行代碼的context或者包含這個變量的函數有關。'with'語句將某個對象添加的做用域鏈的頂部,若是在statement中又某個未使用命名空間的變量,跟做用域鏈中的某個屬性同名,則這個變量將指向這個屬性值。若是沒有同名的屬性,則將拋出RefrenceError異常
另外:with 在嚴格模式下被禁用,替代方式是聲明一個臨時變量來承載你所須要的屬性。
簡單來講,with 能夠減小變量的長度。好比this。使用with不須要在一個函數塊中大量的使用this+"."的方式去訪問對象屬性,能夠直接使用屬性名就能夠訪問到屬性的值。
Object.assign()方法用於將全部可枚舉屬性的值從一個或多個源對象複製到目標對象。它將返回目標對象。
描述:若是目標對象中的屬性具備相同的鍵,則屬性將被源中的屬性覆蓋。後來的源的屬性將相似地覆蓋早先的屬性。
apply(thisArg, [argsArray]) 方法調用一個函數,其具備一個指定的this值,以及做爲一個數組提供的參數。
注意:call()方法的做用和apply()方法相似,只有一個區別,就是call()方法接受的是若干個參數的列表,而apply()方法接受的是一個包含多個參數的數組。
參數:
thisArg。可選參數
在func函數運行時使用的this值。須要注意的是,使用的this值不必定是該函數執行時真正的this值,若是這個函數處於非嚴格模式下,則制定爲null或undefined時會自動替換爲指向全局對象(瀏覽器中就是window對象),同時值爲原始值(數字、字符串、布爾值)的this會指向該原始值的包裝對象。
argsArray 可選參數
一個數組或者類數組對象,其中的數組元素做爲單獨的參數傳給func函數。若是該參數的值爲null或undefined。
返回值:
調用有指定this值和參數的函數的結果。
示例:使用apply來連接構造器(函數的constructor屬性指向函數自己)
// examples Function.prototype.construct = function (aArgs) { var oNew = Object.create(this.prototype);// 定義一個對象,該對象的原型指向函數的原型屬性(prototype) this.apply(oNew,aArgs); //使用該對象繼承函數的對象屬性,這樣就能夠實現constructor指向函數自己 return oNew; } function MyConstructor () { for (var nProp = 0; nProp < arguments.length; nProp++) { this["property" + nProp] = arguments[nProp]; } } var myArray = [4, "Hello world!", false]; var myInstance = MyConstructor.construct(myArray); console.log(myInstance.property1); // logs "Hello world!" console.log(myInstance instanceof MyConstructor); // logs "true" console.log(myInstance.constructor); // logs "MyConstructor"
target.addEventListener(type, listener, options);
參數:
capture:Boolean,表示listener會在該類型的事件捕獲階段傳播到該EventTarget時觸發
once:Boolean,表示listener在添加以後最多隻調用一次。若是是true,listenter會在其被調用以後自動移除。
passive:Boolean。表示listener永遠不會調用preventDefault().若是 listener 仍然調用了這個函數,客戶端將會忽略它並拋出一個控制檯警告。關於該屬性具體介紹,可移步下個關於passive屬性的介紹。
mozSystemGroup: 只能在 XBL 或者是 Firefox' chrome 使用,這是個 Boolean,表示 listener 被添加到 system group。
Boolean,是指在DOM樹中,註冊了該listener的元素,是否會先於它下方的任何事件目標,接收到該事件。沿着DOM樹向上冒泡的事件不會觸發被指定爲usecapture的listener。當一個元素嵌套了另外一個元素,兩個元素都對同一個事件註冊一個處理函數是,所發生的事件冒泡和事件捕獲是兩種不一樣的事件傳播方式。事件傳播模式決定了元素以那個順序接收事件。
注意:那些不支持參數options的瀏覽器,會把第三個參數默認爲useCapture,即設置useCapture爲true
document.addEventListener("touchstart", function(e){ ... // 瀏覽器不知道這裏會不會有 e.preventDefault() },passive:true)
因爲瀏覽器不知道當咱們在移動端監聽touch事件,如touchstart時。是否有作 e.preventDefault,即阻止默認行爲。因此瀏覽器必需要執行完整個監聽函數才知道是否有阻止默認行爲的代碼(好比頁面滾動),從而讓頁面進行滾動。這無疑會對瀏覽器的滾動性能形成卡頓。
而passive屬性,就是爲了告訴瀏覽器,個人監聽事件裏面沒有調用e.preventDefault,這樣瀏覽器就能夠不用管監聽事件裏面的內容,而直接滾動。固然若是監聽器裏面依然調用了e.preventDefault,那麼客戶端也會忽略他,而且拋出一個警告。
對於瀏覽器是否支持passive屬性檢測實例。
var passiveSupported = false; try { var options = Object.defineProperty({},'passive',{ get: function() { passiveSubpported = true; } }) window.addEventLisener("test",null,options); } catch(err){}
這段代碼爲passive屬性建立一個帶有getter函數的options對象;getter設定了一個標識,passiveSupported,被調用後就會把其設爲true。那意味着若是瀏覽器檢查options對象上的passive指時,passiveSupported就會被設置爲true;不然它將保持false.而後咱們調用addEventListener()去設置一個指定這些選項的空事件處理器,這樣若是瀏覽器將第三個參數認定爲對象的話,這些選項指就會被檢查。
而後,當你想實際建立一個是否支持options的事件偵聽器時,你能夠這樣作:
someElement.addEventListener("mouseup",handleMouseUp,passiveSupported ? {passive:true} : false)
一、target:觸發事件的某個對象,通常出現的事件流的目標階段。
二、currentTarget:綁定事件的對象,可能會出如今事件流的任意一個階段中。
三、一般狀況下target和currentTarget是一致的。咱們只要使用target便可,但有一種狀況下,必需要區分這兩者之間的關係,那就是在父子嵌套的關係中,父元素綁定了事件,點擊子元素(根據事件流,在不阻止事件流的前提下他會傳遞至父元素,致使父元素的事件處理函數執行)。這種狀況下,currentTarget指向的是父元素,由於他是綁定事件的對象,而target指向了子元素,由於他是觸發事件的那個具體對象。
示例:
<div id="one"> <div id="three"></div> </div> one.addEventlistener('click',function(e){ console.log(e.target); //three console.log(e.currentTarget) })
一、事件捕獲:事件從window頂層向事件觸發的元素傳播的過程。
二、事件冒泡:事件從觸發事件的元素向window頂層傳播的過程。
三、ie最開始提出的事件冒泡,而w3c提出的是事件捕獲,因此如今纔會有這兩種事件的傳播方式。
四、現代瀏覽器的通常解析這兩種事件流的順序:事件捕獲--》目標階段-》事件冒泡。
經過一個示例看下兩個不一樣的事件流的順序關係。
<div id="one"> <div id="two"> <div id="three"></div> </div> </div> one.addEventLister('click',function(e){ console.log('one'); },false) two.addEventLister('click',function(e) { console.log('two'); },false) three.addEventListener('click',function(e){ console.log('three'); },true); //three //two //one one.addEventLister('click',function(e){ console.log('one'); },true) two.addEventLister('click',function(e) { console.log('two'); },true) three.addEventListener('click',function(e){ console.log('three'); },true); //當三個均爲捕獲時。結果正好相反 //one //two //three //一個是自上而下觸發事件,一個是自下而上觸發事件。因此致使了兩種綁定方式結果的不一樣
addEventListener方法能夠容許傳第二個位置一個參數,告訴瀏覽器這裏你添加的事件是在事件捕獲階段執行,仍是在事件冒泡階段執行。默認參數爲false,爲冒泡。爲true,爲捕獲