一,變數宣告
像在es4中,使用var宣告的變數存在變數提升,下面這樣是不會報錯的。但是在es6中使用的const和let不行,會報錯!!
console.log(a);
var a = 5;
複製程式碼
- 常量(const,不會變數提升,塊級作用域,作用域內值不能改)
- 塊級作用域(let,不會變數提升)
for (let i = 0; i<5; i++) {
setTimeout(() => {
console.log(i) //0 1 2 3 4
},30)
}
for (var i = 0; i<5; i++) {
setTimeout(() => {
console.log(i) //5 5 5 5 5
},30)
}
複製程式碼
特別要說明一點的是 對於const和let都有暫存死區,所謂暫存死區就是:
如果作用域內 有這樣一個變數 那麼這個作用域內就會繫結這個變數,不會繼續向上查詢了,以下程式碼執行會報錯。
const a = 1;
{
console.log(a);
const a = 2;
}
console.log(a)
複製程式碼
二,解構賦值
所謂解構賦值就是 宣告和賦值都放到了一起 一般都是陣列 對 陣列, 物件 對 物件, 陣列能夠設定預設值,物件也能夠設定預設值,預設值必須採用等號的方式
let [zhan, si, xl = 5] = [3, 4];
console.log(zhan, si, xl) //3, 4, 5
let {name, age = 23} = {name: `xl`, bigAge: 24}
console.log(name, age) //xl, 23
複製程式碼
特別的,可能有時會有關鍵字的情況可以通過:的形式來更改名字,看下面程式碼:
let { name, age: xl, default: d } = { name: `xlei`, age: 9, default: `xxx` };
console.log(name, xl, d);
複製程式碼
來一個預設值的具體應用吧:
function ajax({
url = new Error(`url without`),
type = `get`,
data = xxx
}){
console.log(data, type) //{a: 5}, get
}
ajax({
url: `/test`,
data: {a:5}
})
複製程式碼
三,字串
- 模板字串(拼接方便,可以換行)
let exe1 = xlei
let exe2 = `${exe1}nihao
我也好`
複製程式碼
- startWith, endWith 返回一個布林值
let str1 = `www.bsym.online`
let str2 = `http://www.bsym.online`
console.log(str1.startsWith(`http://`)) //false
console.log(str2.startsWith(`http://`)) //true
console.log(str2.endsWith(`online`)) //true
複製程式碼
- padStart, padEnd補全 — 不會刪除原有內容
// padStart padEnd 補全(記住只能增加,不能減少)
let str1 = `nihao`
let newStr = str1.padStart(8,`xl`)
let newStr2 = str1.padEnd(8,`xl`)
console.log(newStr, newStr2) //xlxnihao, nihaoxlx
複製程式碼
四,箭頭函式(解決this問題,書寫起來也更簡單)
傳統函式內的this是定義時所在的環境,而箭頭函式內的this是使用時上下文的環境。
let aa = (arg1, arg2) => {
console.log(arg1, arg2)
}
aa(1, 2) //1, 2
;((arg1, arg2) => {
console.log(arg1, arg2)
})(3, 4);
複製程式碼
這裡順帶提一下,像上面的自執行匿名函式前後都要加分號,這樣既不會被坑,也不會坑別人。另外不要使用箭頭函式的argeuments
五,擴充套件運算子
- 陣列的擴充套件運算子:將一個陣列轉為用逗號分隔的引數序列
let arr = [...[1, 2, 3], ...[4, 5, 6]]
console.log(arr) // 1, 2, 3, 4, 5, 6
console.log(Math.min(...arr)) // 1
複製程式碼
- 物件的解構賦值
物件的 Rest 解構賦值用於從一個物件取值,相當於將所有可遍歷的、但尚未被讀取的屬性,分配到指定的物件上面,注意Rest 解構賦值必須是最後一個引數,否則會報錯。Rest解構賦值所在的物件,拷貝了物件obj的屬性,Rest解構賦值的拷貝是淺拷貝,即如果一個鍵的值是複合型別的值(陣列、物件、函式)、那麼Rest解構賦值拷貝的是這個值的引用,而不是這個值的副本,解構賦值不會拷貝繼承自原型物件的屬性
let obj = {name: `xl`, age: 23, say:`ok`, eat: {xl: `okok`}}
let {name, age, ...z} = obj //尚未被讀取的屬性,分配到指定的物件上面,淺拷貝了物件obj的屬性
obj.say = `oo`
obj.eat.xl = `o?o?`
console.log(name, age, z) //xl 23 { say: `ok`, eat: { xl: `o?o?` } }
複製程式碼
let z = {a: 3, b: 4, c:{
eat:`ok`
}}
let n = {...z} 注意這個地方和直接賦值的區別 let n = z; 一個是淺拷貝物件屬性,一個是淺拷貝物件
z.a = 5
z.c.eat = `ok?`
console.log(n) //{ a: 3, b: 4, c: { eat: `ok?` } }
複製程式碼
那麼要是想實現一個深拷貝,怎麼實現呢?其實就是遍歷屬性如果屬性是一個普通值就賦值,不是普通值就遞迴知道是普通值為止,然後賦值,程式碼如下:
// 實現深拷貝 保留繼承關係 可以實現各種型別的拷貝 實現遞迴拷貝
function deepClone(obj) {
if (typeof obj !== `object`) return obj;
if (obj == null) return null;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
let o = new obj.constructor(); // 保留類的繼承關係
// for (let key in obj) {
// // console.log(obj.hasOwnProperty === Object.prototype.hasOwnProperty)
// if ( obj.hasOwnProperty(key) ) { //只有自身屬性才賦值
// if(typeof (obj[key]) == `object`){
// o[key] = deepClone(obj[key])
// }else{
// // console.log(obj[key])
// o[key] = obj[key]
// }
// }
// }
Object.keys(obj).forEach((key, index) => {
if(typeof (obj[key]) == `object`){
o[key] = deepClone(obj[key])
}else{
// console.log(obj[key])
o[key] = obj[key]
}
})
return o;
}
let o = { a: { a: 1 }, b: function(){
console.log(this.a)
} }
let newObj = deepClone(o);
o.a.a = 2;
console.log( newObj.b());
複製程式碼
六,陣列常用方法
// 1)map返回值 返回值是一個新陣列
Array.prototype.map = function (fn) {
let arr = [];
for (let i = 0; i < this.length; i++) {
arr.push(fn(this[i], i));
}
return arr;
};
let arr = [1, 2, 3].map(item => {
return item * 2;
});
console.log(arr);
// 2)filter 過濾 如果返回true表示留下 返回false表示刪除
let arr = [1, 2, 3];
let filterArr = arr.filter(item => {
return item > 2;
});
console.log(filterArr);
// 3)some找到後返回true,找false可以用every
let r = [2, 1, 3].some(item => {
return item > 2;
});
console.log(r); //true
// 4)every 檢測陣列 ages 的所有元素是否都符合條件 :
var ages = [2, 1, 3];
let r = ages.every((item) => {
return item > 2
})
console.log(r) //false
// 5)Array.from(); 將類陣列轉為陣列
複製程式碼
七,es6的class
先複習一下es5中的幾個名詞:
- 成員屬性(方法)| 例項屬性(方法) :在建構函式中通過this.屬性宣告的
- 靜態屬性(方法):通過類來宣告的 類.xxx
- 私有屬性(方法):只有在類的內部可以使用,其他任何地方都不可以使用的
- 公有屬性(方法)|原型屬性(方法):在原型上宣告的屬性或者方法 xx.prototype.xxx
敲程式碼:
function Parent(name) {
this.name = name; //成員屬性|例項屬性
this.say = function() { //成員方法
console.log(this.name)
}
}
Parent.smoking = `no` //靜態屬性
Parent.prototype.up = function() { //公有方法|原型方法
console.log(`ok`)
}
複製程式碼
再來說說es6中的class(es6中不考慮私有屬性和方法):
class Parent{
constructor(x, y){
this.x = x; //成員屬性|例項屬性 可遍歷 列印例項可直接列印出來, // 與 ES5 一樣,例項的屬性除非顯式定義在其本身(即定義在this物件上),否則都是定義在原型上(即定義在class上)。
this.y = y;
return this.x //如果不返回 預設返回例項物件 this
}
static b(){ // 屬於類上的方法 也稱靜態方法
return 2;
}
eat(){ //原型上的方法 | 公有方法 並且都是不可列舉的 列印例項不能顯示的列印出來
console.log(this.x);
return this.x
}
// Object.assign(Parent.prototype, {
// eat(){},
// });
}
class Child extends Parent{ //
constructor(x, y, z){
super(x, y); // Parent.call(this); 返回的是子類的例項,
this.age = z; // 成員屬性|例項屬性
}
static a(){ // 屬於類上的方法
return 1;
}
smoking(){ // 原型上的方法
return super.eat() + this.age //需要說明的是 super不僅可以呼叫父類的原型方法還可以呼叫父類的靜態方法,方法內部的this指向當前的子類,而不是子類的例項
// console.log(this.age)
}
}
let child = new Child(2, 3, 4);
// console.log(child);
console.log(child.smoking())
class Foo {
constructor() { //constructor函式預設返回this, 這裡返回一個全新的物件,結果導致例項物件不是Foo類的例項
return Object.create(null);
}
}
new Foo() instanceof Foo
// false
//定義類
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return `(` + this.x + `, ` + this.y + `)`;
}
}
var point = new Point(2, 3);
console.log(point)
point.toString() // (2, 3)
point.hasOwnProperty(`x`) // true
point.hasOwnProperty(`y`) // true
point.hasOwnProperty(`toString`) // false
point.__proto__.hasOwnProperty(`toString`) // true
class A {
}
class B extends A {
}
B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true
複製程式碼
以上就是ES6常用的幾個新特性,動手敲一遍,你就記住了!當然以上肯定會存在很多不足的地方,歡迎各位提出寶貴的意見或建議,也希望能幫助到你從中獲得一些知識!