每一次標(biāo)準(zhǔn)的誕生都意味著語言的完善,功能的加強。JavaScript語言本身也有一些令人不滿意的地方。
? ? 變量提升特性增加了程序運行時的不可預(yù)測性
? ? 語法過于松散,實現(xiàn)相同功能,不同的人可能會寫出不同的代碼
ES6的新增語法
let:ES6中新增的用于變量聲明的關(guān)鍵字
? ? let聲明的變量只在所處于的塊級有效
例:
if (true) {
? ? let a = 10;
}
console.log(a);? ? // a is not defined
? ? 在一個大括號中使用let關(guān)鍵字聲明的變量才具有塊級作用域,var關(guān)鍵字不具備這個特點
例:if (true) {
? ? let num = 100;
? ? var abc = 200;
}
console.log(abc);????//輸出200
console.log(num);? ? //"abc" is not defined
? ? 放置循環(huán)變量變成全局變量
例:for (var i = 0; i < 3; i++) {
}
console.log(i);? ? //任然可以輸出
for (let i = 0; i<3; i++) {
}
console.log(i);? ? //現(xiàn)在就不可以輸出,比較符合邏輯
? ? 不存在變量提升
例: console.log(a);????//a is not defined (需要先聲明再使用)
let a = 20;
????暫時性死區(qū)
例:var tmp = 123;
if (true) {
????tmp = 'abc';? ? //會報錯,報變量沒有聲明的錯誤
? ? let tmp;
}????
if中的tmp和全局中的tmp互不干擾
經(jīng)典面試題:
var arr = [];
for (var i = 0; i < 2; i++){
? ? arr[i] = function (){
? ? ? ? console.log(i);
????}
}
arr[0]();? ? //2倆次輸出的結(jié)果都是全局變量里面的i
arr[1]();? ? //2
此題的關(guān)鍵點在于全局變量i是全局的,函數(shù)執(zhí)行時輸出的都是全局作用域下的值
把其中的var換成let,結(jié)果就大不一樣
let arr = [];
for ( let i = 0;i < 2; i++) {
? ? arr[i] = function () {
? ? console.log(i);
????}
}
arr[0]();? ? //0? ? 此時輸出會查找塊級作用域里面的i,而不是全局查找
arr[1]();? ? //1

????此題的關(guān)鍵點在于每次循環(huán)都會產(chǎn)生一個塊級作用域,每個塊級作用域的變量都是不同的,函數(shù)執(zhí)行時輸出的是自己上一級(循環(huán)產(chǎn)生的塊級作用域)作用域下的i值。
const:聲明常量,常量就是值(內(nèi)存地址)不能發(fā)生變化的量
? ??具有塊級作用域
例:if (true) {
? ? const a = 10;
}
console.log(a) //? ? a is not defind
? ? 聲明常量時必須賦值
例: const PI;? ? //Missing initializer in const declaration再聲明const常量時丟失了初始值
? ? 常量賦值后,值不能修改
例: const PI = 3.14;
? ? PI = 100;? ? //Assignment to constant variable.
特殊情況:
const ary = [100,200];
ary[0] = 'a';
ary[1] = 'b';
console.log(ary);? ? //['a','b'];????可以賦值,因為改變的是值,不是內(nèi)存地址
ary = ['a','b'];? ? //Assignment to constant variable.這樣是不容許的,這樣改變了ary在內(nèi)存中的存儲地址
總結(jié)let、const、var區(qū)別
? ? 1、使用var聲明的變量,其作用域為該語句所在的函數(shù)內(nèi),且存在變量提升現(xiàn)象。
? ? 2、使用let聲明的變量,其作用域為該語句所在代碼塊內(nèi),不存在變量提升現(xiàn)象。
? ? 3、使用const聲明的常量,在后面出現(xiàn)的代碼中不能在修改常量的值。

解構(gòu)賦值
? ? ES6中允許從數(shù)組中提取值,按照對應(yīng)位置,對變量賦值。對象也可以實現(xiàn)解構(gòu)。
? ? 按照一定模式,從數(shù)組或?qū)ο笾刑崛?,將提取出來的值賦值給另外的變量
數(shù)組解構(gòu)
例:數(shù)組與變量一一對應(yīng)的情況
let arr = [1, 2, 3]
let [a, b, c] = arr;? ? //等號左邊中括號中的abc為三個變量,與arr中的值為一一對應(yīng)的關(guān)系,并且用來接收arr中的值
console.log(a);? ? //輸出為1
console.log(b);? ? ?//輸出為2?
console.log(c);? ? ?//輸出為3?
變量與數(shù)組中的值不對應(yīng)
let [foo] = [];
let[bar ,foo] = [1];? ? //bar對應(yīng)的值為1 foo對應(yīng)的值為undefined
對象解構(gòu)
對象解構(gòu)允許我們使用變量的名字匹配對象的屬性 匹配成功將對象屬性的值賦值給變量
例:
let person = {name : 'xijiaxin'; age : 22; sex : '男'};
let { name, age, sex } = person;
console.log(name);? ? //xijiaxin
console.log(age);? ? //22
console.log(sex);? ? //男
對象解構(gòu)的其他用法
let person = {name : 'xijiaxin'; age : 22; sex : '男'};
let {name : myName, age : myAge} = person;????// 以name : myName為例,先用name去匹配person里面的name,再把匹配到的值賦值給myName變量
console.log(myName); ????//????'xijiaxin'
console.log(myAge);? ? //? ? 22
箭頭函數(shù)——ES6中新增的定義函數(shù)的方式
箭頭函數(shù)是用來簡化定義函數(shù)語法
箭頭函數(shù)基本語法:() => {}
例:const fn = () => {
? ? console.log('123');
}
fn();? ? //123
函數(shù)體中只有一句代碼,且代碼的執(zhí)行結(jié)果就是返回值,可以省略函數(shù)體的大括號
例:? ? function sum(num1, num2) {
? ? return num1 + num2;
}? ? //用原來方法實現(xiàn)倆數(shù)相加
const sum = (num1, num2) => num1 + num2;? ? //用箭頭函數(shù)實現(xiàn)
在箭頭函數(shù)中,如果形參只有一個,可以省略形參外部的小括號
const fn = (i) => {
? ? alert(i);
};
fn(20);? ? //沒有省略括號寫法
const fn = i => alert(i);? ? //簡化寫法
箭頭函數(shù)不綁定this關(guān)鍵字,箭頭函數(shù)中的this,指向的是函數(shù)定義位置的上下文this
function fn () {
????console.log(this);? ? //? ? {'name':'xijiaxin'}
????return () => {? ? //此時,箭頭函數(shù)被定義在了fn的內(nèi)部,箭頭函數(shù)的this指向的是fn中的this
? ? ? ? console.log(this);? ? //? ? {'name':'xijiaxin'}
????}?
}
const obj = {name : 'xijiaxin'}
cosnt res = fn.call(obj);? ? //先用call改變fn的this指向,再用res接收fn的返回值
res();
箭頭函數(shù)面試題
var obj = {
? ? age : 20,
? ? say : () =>{
? ? alert(this.age)
????}
}
obj.say();? ? //結(jié)果為undefined,因為obj是一個對象,他沒有形成作用域。此時的箭頭函數(shù)相當(dāng)于定義在了全局,就沒找到age
剩余參數(shù)
? ? 剩余參數(shù)語法允許我們將一個不定數(shù)量的參數(shù)參數(shù)表示為一個數(shù)組。
例:
function sum (first, ...args) {
? ? console.log(first);? ? //10
? ??console.log(args);? ? ?//[20,30]? ? 再args前面加三個點,就讓剩余的實參以數(shù)組形式賦給args
}
sum(10,20,30);
數(shù)組內(nèi)所有項的和
const sum = (...args)? ? =>????{
? ? let total = 0;
? ? args.forEach(item => total +=item);? ? //其中遍歷到的item的每一項相加
? ? return total;
};
sum(10, 20);
sum(10, 20, 30);
剩余參數(shù)和解構(gòu)配合使用
let students = ['xian', 'ouya', 'xuanyuan'];
let [s1, ...s2] = students;? ? //? ? 此時,s2接收了除去對應(yīng)s1的值以外的所有值
console.log(s1);? ? //????'xian'
console.log(s2);? ? //? ? ['ouya', 'xuanyuan']
Array的擴展方法
擴展運算符(展開語法)——擴展運算符可以將數(shù)組或者對象轉(zhuǎn)換為用逗號分隔開的參數(shù)序列。
let ary = [1, 2, 3];
...ary // 1,2,3? ? 輸出結(jié)果應(yīng)該為1,2,3? ,ary是由逗號分隔開的參數(shù)
console.log(...ary);? ? // 1 2 3? ? 輸出結(jié)果為123,原因是這里的逗號被認(rèn)為是參數(shù)分隔符,所有不顯示就相當(dāng)于
console.log(1, 2, 3);? ? //相當(dāng)于這樣的輸出結(jié)果
例:
let ary1 = ["a", "b", "c"];
console.log(...ary1);? ? //? ? a b c
console.log("a", "b", "c");? ? //? ? a b c 輸出結(jié)果相同
擴展運算符可以應(yīng)于合并數(shù)組。
//方法一
let ary1 = [1, 2, 3];
let ary2 = [3, 4, 5];
let ary3 = [...ary1, ...ary2];? ? //...ary1 = 1,2,3 ary2 = 3,4,5? 所以ary3 = [...ary1, ...ary2] = [1, 2, 3, 3, 4, 5]
利用擴展運算符將偽數(shù)組轉(zhuǎn)換為真正的數(shù)組
<div></div>
<div></div>
<div></div>
<script>
var oDivs = document.getElementsByTagName('div');
console.log(oDivs)? ? //此時獲得的是一個類數(shù)組
var ary = [...oDivs];? ? //把類數(shù)組轉(zhuǎn)換為可以操作的數(shù)組
ary.push('a');
console.log(ary);? ? //輸出結(jié)果為[ div,div,div,a]
</script>
構(gòu)造函數(shù)方法: Array.from()——將類數(shù)組或可遍歷的對象轉(zhuǎn)換為真正的數(shù)組
let arrayLike = {
? ? '0' : 'a',
? ? '1' : 'b',
? ? '2' : 'c',
length:3
};
let arr2 = Array.from(arrayLike);? ? //? ? ['a', 'b', 'c']
Array.from()——方法還可以接收第二個參數(shù),作用類似于數(shù)組的map方法,用來對每個元素進行處理,將處理后的值放入返回的數(shù)組。
例: var arrayLike = {
? ? "0" : "1",
????"1" : "2",
????"length" : 2
}
var ary = Array.from(arrayarLike,item => item*2);? ? //? ? 給循環(huán)出來的每一項值都乘2
console.log(ary);? ? //? ? 輸出結(jié)果為[2,4]
Array.find()——用于找出第一個符合條件的數(shù)組成員,如果沒有找到返回undefined
let ary = [{
? ? id : 1,
? ? name : '西安'
},{
? ? id : 2,?
? name : '歐亞'
}];
let target = ary.find((item, index) => item.id==2);? ? ? ?//這個函數(shù)需要攜帶倆個參數(shù),當(dāng)前循環(huán)項,以及當(dāng)前循環(huán)項所攜帶的索引值
console.log(target)????//????輸出結(jié)果為id:1 name:"西安"
它接收一個函數(shù)作為參數(shù),在參數(shù)函數(shù)體中,要返回一個布爾值,相當(dāng)于是否滿足查找的條件
Array.findIndex()——用于找出第一個符合條件的數(shù)組成員的位置,如果沒有找到返回-1
let ary = [1, 5, 10, 15];
let index = ary.findIndex((value, index) => value > 9);
console.log(index);? ? //? ? 此時輸出為2
用法基本與find()一樣,同樣是需要傳一個函數(shù)為參數(shù),在參數(shù)函數(shù)體中,需要返回一個布爾值,相當(dāng)于是否滿足查找的條件,用于判斷。
Array.includes()——表示某個數(shù)組是否包含給定的值,返回布爾值
[1, 2, 3].includes(2);? ? //true?
[1, 2, 3].includes(4);? ? //false
String的擴展方法
模板字符串——ES6新增的創(chuàng)建字符串的方式,使用反引號定義。
let name = `xijiaxin`;??//? ? 模板字符串聲明
模板字符串可以解析變量
let name = 'xijiaxin';
let sayHello = `hello,my name is ${name}`;????//? ? 輸出hello,my name is xijiaxin
模板字符串中可以換行
?let?result?=?{?
???????????name:?"xijiaxin",???
?????????????age:?22,??????
??};????????
let?html?=?`????????
????<div>????????
????????<span>${result.name}</span>????????????
????????<span>${result.age}</span>???????
????</div>???????
?`????
????console.log(html)

模板字符串中可以調(diào)用函數(shù)
????????const?fn?=?()?=> {
????????????return?'我還可以調(diào)用函數(shù)'
????????}
????????let?html?=?`我是模板字符串,${fn()}`
????????console.log(html)

String實例方法:startsWith() 和 endsWith()
? ? startsWith():表示參數(shù)字符串是否在源字符串的頭部,返回布爾值
? ? endsWith():表示參數(shù)字符串是否在原字符串的尾部,返回布爾值
?例: let?str?=?'Hello?world!';
????????let?r1?=?str.startsWith('H');? ? // ????r1輸出為 true
????????let?r2?=?str.endsWith('!');? ? //????r2輸出為true
String實例方法:repeat()——reeat方法表示將原字符串重復(fù)n次,返回一個新字符串
例:
"y".repeat(5);? ? //? ? 表示將"y"重復(fù)5次顯示,想重復(fù)幾次就在括號里傳幾
Set數(shù)據(jù)結(jié)構(gòu)
ES6提供了新的數(shù)據(jù)結(jié)構(gòu)Set。它類似于數(shù)組,但是成員的值都是唯一的,沒有重復(fù)的值。Set本身是一個構(gòu)造函數(shù),用來生成Set數(shù)據(jù)結(jié)構(gòu)。
const s = new Set();
Set函數(shù)可以接收一個數(shù)組作為參數(shù),用來初始化。
const set = new Set([1, 2, 3, 4]);
Set函數(shù)的值是唯一的
????????let?set?=?new?Set(["a",?"b",?"a",?"b"]);
? ? ? ? ? ? //console.log(set);? ? //? ? 得到的類數(shù)組只有倆個值,重復(fù)的就被去除了
//????獲得類數(shù)組后
let ary = [...set]? ? //? ? 把獲得的類數(shù)組打散裝進數(shù)組
console.log(ary)


Set實例方法:
? ? add(value):添加某個值,返回Set結(jié)構(gòu)本身
? ? delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功
????has(value):返回一個布爾值,表示該值是否為Set成員
????clear():清除所有成員,沒有返回值
Set中取值——Set結(jié)構(gòu)的實例與數(shù)組一樣,也擁有forEach方法,用于對每個成員執(zhí)行某種操作,沒有返回值
s.forEach(value => console.log(value))
???? 例:? ?const?s5?=?new?Set(['a','b','c'])
????????s5.forEach(value?=>{
????????????console.log(value)
????????})
