注:由於是直接從Typora文件複製粘貼過來的,因此有些格式可能會錯位,見諒 須要這個文件的同窗能夠直接發郵件給我 408579331@qq.comnode
var tem = 123;
if(true){
console.log(tem); // 報錯
let tem = 0;
}
let a = a ; // 報錯
let b = 0;
let b = 1; // 報錯
複製代碼
【注】ES5 中 不容許塊級做用域中聲明函數,但爲了兼容老代碼,因此ES6的規定中瀏覽器能夠不遵照此規定,有本身的行爲方式,因此通常函數的聲明會像 var同樣會進行函數名的提高,可是隻做用於當前的塊級做用域es6
【注】ES6 中 塊級做用域中函數的聲明必須包含在 { } 中,如 if(true) f(){}; 會報錯,正確寫法if(true) { f(){} };ajax
<1> 用於聲明一個常量的值,一旦聲明,常量的值就不能改變,若改變則會報錯正則表達式
<2> 聲明時必須賦值,若只聲明不賦值,就會報錯算法
<3> 做用域與 let 相同,只存在於當前做用域中json
<4> 沒有預解析數組
<5> 存在暫時性死區的特性promise
<6> 同一個變量不能屢次聲明瀏覽器
本質:const實際上保證的是變量指向的那個內存地址所保存的值是不能改變的,因此:服務器
const PI = 3.141592654;
console.log(PI);
PI = 3 ; // 報錯
const a ; //報錯
const b = [];
b.push('hello'); // 可執行
b.length = 10; // 可執行
b = ['aaa'] // 報錯
// 若是想將對象凍結,需使用 Object.freeze() 方法 freeze:凍結
var c = Object.freeze({});
// 常規模式下,下面這行代碼不起做用
// 嚴格模式下會報錯
c.prop = 123;
複製代碼
在 ES5 中 瀏覽器的頂層對象就是 window ,頂層對象的屬性與全局變量時等價的 Node 裏面,是 global 在 ES6 中 ,var 和 function聲明的變量依舊是頂層對象的屬性,但 let const class 聲明的全局變量不屬於頂層對象的屬性
解構:ES6中容許按照必定模式,從數組和對象中提取值,對變量進行賦值,這稱之爲解構 數組的解構賦值是按照元素的順序依次賦值
let [a,b,c] = [1,2,3]
// a:1 b:2 c:3
let [,,a] = [1,2,3]
// a:3
let [a,b] = [1,2,3]
// a:1 b:2
let [a,...b] = [1,2,3,4]
// a:1 b:[2,3,4]
// ... 擴展運算符,將一個數組變成參數序列
let [a,b,...c] = [1]
// a:1 b:undefined c:[]
let [a] = [];
// a:undefined
let [a] = 1;
// 報錯
// 默認值
//**注意:當一個數組成員嚴格等於( === )undefined時,默認值纔會生效**
let [x=1] = [undefined];
// x:1
let [x=1] = ['undefined'];
// x:'undefined'
let [x=1] = [null];
// x:null;
let [x=1] = [2];
// x:2
複製代碼
變量與對象的解構賦值是變量與屬性同名,再進行賦值 例:let {a} = {a:1} 對象與對象的解構賦值是先找到同名的屬性,再賦值給對應的變量 例:let {a:b} = {a:1} b=>1
let {x,y}={x:1,y:2};
// x:1 y:2;
// 當變量名與屬性名不一致時
let a = {x:1,y:2};
let {x:a,y:b}=a;
// a:1 b:2
let {a:b} = {a:2};
// b:2
// a:報錯,not undefined
// 對象與對象的解構賦值的內部機制,是先找到同名屬性,而後再賦給對應的變量。真正被賦值的是後者,而不是前者
// 例:
const node = {loc: {start: {line: 1,column: 5}}};
let { loc, loc: { start }, loc: { start: { line }} } = node;
console.log(loc); {start:{line:1,column:5}}
console.log(start); {line:1,column:5}
console.log(line); 1
let { loc, loc: { start }, loc: { start: { line }} } =
{loc: {start: {line: 1,column: 5}}};
// 例2
let obj = {p: ['Hello',{ y: 'World' }]};
let { p, p: [x, { y }] } = obj;
console.log(p); ['Hello',{ y: 'World' }]
console.log(x); 'Hello'
console.log(y); 'World'
// 例3
let obj = {};
let arr = [];
({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });
console.log(obj); {prop:123}
console.log(arr); [true]
不加一對小括號時,js在行首遇到{}會解析成代碼塊,從而引起語法錯誤
// 有默認值時
//**注意:當一個數組成員嚴格等於( === )undefined時,默認值纔會生效**
let {a,b=1}={a:1};
// a:1 b:1
let {x: y = 3} = {};
// y:3 x:報錯,not undefined
let {x,y = 3} = {};
// y:3 x:undefined
let {foo: {bar}} = {baz: 'baz'};
// 報錯,由於foo是undefined,因此它的子對象就會報錯
// 數組的解構賦值
let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
// 因爲數組的本質是一個特殊的對象,因此 arr=>{0:1,1:2,2:3} ?
console.log(first);
console.log(last);
複製代碼
const [a,b,c,d,e] = 'hello';
// a:'h'
// b:'e'
// c:'l'
// d:'l'
// e:'o'
let {length:len} = 'hello'
// len:5
// 字符串是一個類數組,因此具備 length 屬性
複製代碼
解構賦值的規則:只要等號右邊的值不是對象或者數組,就先將其轉換成對象,在進行賦值
let {toString:s} = 123;
s === Number.prototype.toString // true
let {toString:s} = true
s === Boolean.prototype.toString // true
// 由於 數值和布爾 的包裝對象都具備 toString 屬性,因此 變量s 都會被賦值
let {toString:x} = undefined ; // 報錯:TypeError
let {toString:x} = null ; // 報錯:TypeError
複製代碼
function xy([a,b]){
return a+b;
}
xy([1,2]) ===> 3
let arr = [[1,2],[3,4]].map(([a,b])=>a+b);
// .map()方法:數組中的每個元素執行map方法中的函數或者方法,返回一個新的數組
// arr ===> [3,7]
// 函數參數也可使用默認值
// 變量默認值
function xy({x=0,y=0}={}){
return x+y;
}
xy({x:1,y:2}) ===> 3
xy({x:1,a:2}) ===> 1
xy({}) ===> 0
xy() ===> 0
// 參數默認值
function move({x,y}={x:0,y:0}){
return x+y;
}
move({x:1,y:2}) ===> 3
move({x:1}) ===> NaN 由於 y的值是undefined,因此最終結果爲NaN
move({}) ===> NaN
// 注意:上述是爲參數指定默認值,而不是變量
複製代碼
// (1). 交換變量的值
let x = 1;
let y = 2;
[x,y] = [y,x];
// (2). 函數返回多個值
function xy(){
return [1,2,3,4];
}
let [a,b,c,d] = xy();
// a:1 b:2 c:3 d:4
// (3). 函數參數的定義
function xy([x,y,z]){ ... }
xy([1,2,3])
function xy({x,y,z}){ ... }
xy({z:1 , y:2 , x:3})
// (4). 提取 JSON 數據
let jsonData = {
id:1,
status:'OK',
data:[111,222]
}
let {id,status,data:arr} = jsonData;
// id:1 status:'OK arr:[111,222]
// (5). 函數參數的默認值
let ajax = function(url,{ async = true, // async 異步 beforeSend = function(){},
cache = true, // 隱藏
complete = function(){}, // complete 完整的,完成
crossDomain = false, // cross 交叉 domain 領域
global = true, // 全球的,整體的
} = {} ){ ... }
// (6). 遍歷map解構
const map = new Map([
[{a:1},1]; // 鍵是對象
['a',1] // 鍵是字符串
]);
/* Map()構造函數,是一個鍵值對的集合,其中鍵能夠時任意類型 集合是一個數組,其中數組中的每個數組項都是Map實例的鍵和值*/
map.set('first','hello'); // 添加一組鍵值對
map.get('first') // 獲取指定的屬性值
map.has('first') // 判斷是否存在某個屬性,返回bool
map.delete('first') // 刪除指定的屬性,返回bool
map.size; // 獲取數組的長度
map.clear() // 清除全部
// map 的遍歷方法--返回一個迭代器,相似一個對象?
.keys() // 返回鍵名的遍歷器
.values() // 返回鍵值的遍歷器
.entries()// 返回全部成員(鍵值對)的遍歷器
.forEach()// 遍歷Map的全部成員
// 例:
for(let val of map.kes()){
console.lof(val);
}
for(let [key,value] of map.entries()){
console.lof(key+"==="+value);
}
// 只想得到鍵名
for(let [key] of map){
console.log(key);
}
// 只想得到值
for(let [,val] of map){
console.log(value);
}
// Set() 構造函數
複製代碼
// 能夠以 \uxxxx 表示一個字符,其中 xxxx 時 Unicode碼點
'\u{7A}' === 'z'
複製代碼
// 對於字節超出 Unicode 碼點的字符,charAt()方法沒法讀取
// 因此提供了 codePointAt()方法來讀取碼點
複製代碼
// 經過碼點獲取字符,能夠識別編號大於 0xFFFF 的字符編碼
String.fromCodePoint(0x20BB7);
複製代碼
// 使用 for of 遍歷字符串,能夠識別大於 0xFFFF 碼點的字符
for(let code of 'foo'){
console.log(code); // 'f' 'o' 'o';
}
複製代碼
/* 用於他國語言的語調符號和重音符號 Ǒ(\u01D1)和 O(\u004F)和ˇ(\u030C)合成Ǒ(\u004F\u030C) 兩種合成符的判斷,js中直接判斷爲false ,加上 .noemalize()方法後爲true */
複製代碼
let s = "Hello World";
s.startsWith("Hello") // true 判斷參數是否在字符串的開頭
s.endWith("World") // true 判斷參數是否在字符串的結尾
s.includes('o') // true 判斷是否存在該字符串
s.startWith("World",6) // true 從第6個位置到結束是不是以"World"開頭
s.includes("Hello",6) // false 從第6個位置到結束中是否包含指定字符串
// 注意--------------
s.endWith("Hello",5) // 前5個字符中是否包含指定字符串
複製代碼
// 返回一個新字符串,表示將指定字符串複製n次
let str = "a".repeat(2); // "aa";
let str = "xy".repeat(2); // "xyxy";
// 參數爲小數則會取整,負數則報錯,0則是一個空字符串
let str = "xy".repeat(2.9); //"xyxy"
let str = "xy".repeat(-1); // 報錯
let str = "xy".repeat(0); // 空字符串
// 若是參數是 0~-1之間的小數,則會先取整,也就是按 0 計算
// 若是參數是 NaN 則會按 0 進行計算
// 若是參數是字符串,則先會用 Number() 進行轉換再進行計算
複製代碼
// 字符串填充
.padStart() // 頭部補全
.padEnd() // 尾部補全
'xy'.padStart(3,'0'); // "0xy"
'xy'.padEnd(4,'0'); // "xy00"
'xy'.padStart(5,'ab'); // "abaxy"
'xy'.padEnd(5,'ab'); // "xyaba"
// 第二個參數省略,默認用空格補全
'xy'.padEnd(5); // "xy "
複製代碼
// 返回一個正則表達式在當前字符串的全部匹配
複製代碼
let str = `<div>${a+1}</div>`;
let str = `<div>${fn()}</div>`;
複製代碼
// 返回指定索引對應的字符
let str = "123456"
at(0) // 1
複製代碼
// 判斷一個數值是否爲整數
Number.isInteger(25); // true
Number.isInteger(25.5); // false
複製代碼
/* 可以接受的偏差範圍 Number.EPAILON 是一個常量,表示1與大於1的最小浮點數之差,即 1 與 1.000...0001(51個零) 等同於 Math.pow(2,-52) 經常使用於浮點數計算後的偏差判斷,若是小於這個值,則表示偏差沒有意義,即:不存在偏差*/
function withinErrorMargin (left, right) {
return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);
}
複製代碼
// 判斷整數是否是在 -2^53 到 2^53 之間,由於在js內超過這個數值,判斷就會出錯
Number.isSafeInteger(num) // 返回一個布爾值,注意,只判斷數字,其他都爲 false
複製代碼
// 1. Math.trunc()
// 用於去除一個數的小數部分,返回整數部分
Math.trunc(1.222) // 1
Math.trunc(-0.111) // 0
// 對於非數字,會先用 Number() 進行內部轉換
Math.trunc(true) // 1
Math.trunc(false) // 0
// 轉換失敗則返回 NaN
Math.trunc(NaN) // NaN
Math.trunc('foo') // NaN
Math.trunc() // NaN
Math.trunc(undefined) // NaN
// 2. Math.sign()
// 判斷一個數是 正數 負數 零 ,若是是非數值,則會先進行 Number() 轉換
// 返回 1:正數 -1:負數 0:零 -0:(輸入-0的時候) NaN:轉換失敗 報錯:參數語法錯誤時
Math.sign(55) // 1
Math.sign(-1546) // -1
Math.sign(0) // 0
Math.sign(-0) // -0
Math.sign('ss') // NaN
Math.sign(2aa) // 報錯
// 3. Math.cbrt()
// 用於計算一個數的立方根 , 若是是非數值,則會先進行 Number() 轉換
// 返回: 計算後的值 NaN
Math.cbrt(8) // 2
Math.cbrt('8') // 2
Math.cbrt('ss') // NaN
// 4. Math.hypot()
// 返回全部參數的平方和的平方根
// 若是參數不是數值,則會先用 Number() 進行轉換,只要有一個爲NaN,則返回 NaN
// 能夠寫多個參數
Math.hypot(3,4) // 5
Math.hypot() // 0
Math.hypot(NaN) // NaN
Math.hypot(3,4,'a') // NaN
複製代碼
2 ** 2 // 4
2 ** 3 // 8
2 ** 4 // 16
// 計算方式是右結合,即從右往左計算
2 ** 3 ** 2 ==> 2 ** (3 ** 2) // 512
// 能夠與 = 結合
let a = 2;
a **= 3 // 8
複製代碼
function abc(a=1, b=2){
ruturn a+b;
}
// 注意:使用參數默認值時,函數不能有同名的形參
// 參數也能夠是一個表達式
let i = 100;
function abs(y = i + 1){
console.log(y);
}
abs(); // 101
// 與解構賦值一塊兒使用
function foo({x,y = 5} = {}){
console.log(x,y);
}
foo({x:1, y:2}); // 1,2
foo(); // undefined 5
// 注意,若是不設置默認值是 foo()調用會出錯,由於只有foo的參數是一個對象時,x,y纔會經過結構賦值生成,若果不生成就會報錯
// 當知道了默認值後,函數length屬性的計算將去掉該參數
// 函數.length : 該函數預約義傳入參數的個數
(function(a, b = 1){}).length // 1
// 做用域
// 當設置的參數的默認值時,函數聲明初始化時會造成一個單獨的 參數 做用域,當初始化結束,該做用域消失
// 若是沒有設置默認值,則不存在該做用域
function abc(x, y = x){ return y;}
// 當abs進行初始化時,參數會造成一個單獨的做用域,此時 y 的默認值 x 指向 第一個參數 x
// 因此 abc(90) 會返回 90
let x = 1;
function foo(y = x){
let x = 2;
console.log(y);
}
// 當foo進行初始化時,參數會造成一個單獨的做用域,因爲做用域鏈的問題,因此 x 會像上查找,
// 查找不到則會報錯,即:此時初始化結束後就至關於 y = 1 ;
複製代碼
ES6中引入了rest參數(形式爲 ...變量名),用於獲取函數的多餘參數,獲取後的格式爲一個數組
function foo(x, ...values){
let sum = 0 + x;
for(let val of values){
sum += val;
}
return sum;
}
foo(1,2,3,4,5,6) 21
// 函數的 length 屬性不包括 rest 參數
複製代碼
// 返回該函數的函數名
function foo(){};
foo.name; // 'foo'
var a = function(){};
a.name; // ES5總爲 '' ES6中爲 'a'
複製代碼
注意:使用了箭頭函數後,這個函數裏面就沒有本身的this,裏面所出現的this是外部函數的this,而不是指向的this,這種狀況也稱爲this指向的固定化
// 只有一個參數
let f = v => v;
// 等同於
let f = function (v) {
return v;
}
// 無參數
let f = () => 5;
// 等同於
let f = function () {
return 5;
}
// 多個參數
let sum = (num1,num2) => num1 + num2;
// 等同於
let sum = function(num1, num2){
return num1 + num2;
}
// 返回一個對象
// 因爲代碼塊是用 {} 包含起來的,因此返回一個對象時需用 () 包含起來,不然對象的 {} 會被解析成函數體
let a = id => ({id:id,num:1})
// 與解構賦值一塊兒使用
let a = ({first,last}) => first + '' + last;
// 與 rest 參數一塊兒使用
let a = (...arr) => arr;
複製代碼
改變this指向,即:雙冒號左邊的對象是右邊函數中的this
// 1. obj::foo
等同於 foo.bind(obj)
複製代碼
尾調用:指某個函數的最後一步調用了一個函數,即:return y(x); 的嚴格格式 尾調用優化:每一次函數調用都會在內存中造成一個"調用記錄",又稱「調用幀」,保存調用位置和內部變量等信息,全部的調用幀稱之爲 調用棧 ,若是內部函數用到外部函數的變量,就不會進行尾調用優化
尾遞歸:函數調用自身,稱之爲遞歸,尾調用自身,稱之爲尾遞歸
// ... ,將一個數組轉爲用逗號分割的參數列表,內部使用for...of循環
console.log(...[1,2,3]) // 1 2 3
// 通常用於函數調用
let arr = [1,2,3,4,5,6];
foo(...arr)
// 數組最大值判斷
let arr = [1,2,3,4,5,6];
Math.max(...arr);
// 數組中的每一項添加到另外一個數組中
let arr = [1,2,3,4];
let brr = [5,6,7,8];
arr.push(...brr);
// 數組複製--淺拷貝
let arr = [1,2,3];
let brr = [];
brr = [...arr];
// 數組合並--淺拷貝
let arr = [1,2,3,4];
let brr = [5,6,7,8];
let crr = [...arr , ...brr];
// 數組與結構賦值一塊兒使用
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
// 字符串轉數組
let arr = [...'hello']
// ['h','e','l','l','o']
// 類數組轉換成規定的數組
let liArr = document.querySelectorAll('li');
let arr = [...liArr];
/* query.selectorAll 方法返回的是一個NodeList對象。不是一個數組,而是一個相似數組的對象, 之因此能夠用數組的方法,是由於nodeList對象實現了Iterator(迭代)接口*/
複製代碼
將兩類對象轉換成規定的數組:相似數組的對象(具備length屬性),可遍歷迭代對象 若是參數是一個規定的數組,該方法會返回一個如出一轍的新數組------即:複製
let arrayLike = {
'0':'a',
'1':'b',
'2':'c',
length:3
}
let arr = Array.from(arrayLike);
// ['a','b','c','d']
Array.from()方法還有第二個參數,做用相似於map()方法,將數組中的被一個元素進行處理並返回
Array.from(arr,x=>x*x)
// 等同於
Array.from(arr).map(x=>x*x);
// 例:取出每一個節點的內容,並造成一個數組
let liObj = document.querySelectorAll('li');
let arr = Array.from(li,v=>v.innerHTML);
// 例:將布爾值爲false的數組項轉換成0
let arr = [1,2,,3,,5,,0,];
let brr = Array.from(arr,v=>v||0);
// [1, 2, 0, 3, 0, 5, 0, 0]
複製代碼
用於將一組值轉換成數組
Array.of(1,2,3);
// [1,2,3]
複製代碼
var arr = ['a','b','c', 1,2,3]
arr.keys(); // 返回一個對鍵名的遍歷器---- 一個對象
arr.values(); // 返回一個對鍵值的遍歷器---- 一個對象
arr.entries(); // 返回一個對鍵值隊的遍歷器---- 一個對象
// 遍歷器中有一個next()方法,裏面存放着一條數據,可循環調用來一次輸出結果
arr.keys().next(); === {value: 0, done: false}
arr.values().next(); === {value: "a", done: false}
arr.entries().next(); === {value: Array(2), done: false}
arr.entries().next().value; === [ 0,'a']
// 例:用 for of 來循環遍歷
for(var [key,value] of arr.entries()){
console.log(key+"="+value);
}
// 0='a' 1='b' 2='c' 3=1 4=2 5=3
複製代碼
// 將多維數組「拉平」
[1,[2]].flat();
// [1,1]
[1,[2,[3]]].flat();
// [1,2,[3]] 默認拉平一層,從外向內拉平
// flat(number);
number:設置拉平的層數
Infinity 關鍵字,表示無限
// 若是數組有空位,flat()方法會跳過空位
[1,2,3,,4].flat();
// [1,2,3,4]
複製代碼
// 對原數組的每個成員執行一個函數(至關於執行了map()方法),返回一個新數組
// 執行完後再執行flat()方法
[1,2,3,4,5,6].flatMap(x=>x*x); //[1,4,9,16,25,36]
[1,2,3,4].flatMao(x=>[x,x*x]); //[1,1,2,4,3,9,4,16]
複製代碼
/* ES6中 Array.from(),(...),entries(),keys(),values(),find(),findIndex() 等會將空位處理成 undefined */
[...[,1]] // [undefined,1]
複製代碼
// ES6 容許直接在對象中直接寫入變量,此時,變量名爲屬性名,變量值爲屬性值
let aaa = 1;
let obj = {aaa}; // {'aaa':1}
複製代碼
let aaa = 'a'
let obj = {
['a'+'bc']:1,
[aaa]:2
}
obj.abc // 1
obj.a // 2
obj.aaa // undefined
obj[aaa]// 2
複製代碼
// 對象中的每一個屬性的都有一個描述對象(Descriptor),用來控制該屬性的行爲
Object.getOwnPropertyDescriptor() 方法能夠獲取該屬性的描述對象
let obj = {foo:123};
Object.getOwnPropertyDescriptor(obj,'foo'); // 返回一個對象
// {
// value: 123,
// writable: true,
// enumerable: true, //可枚舉性
// configurable: true
// }
// 由於for in 遍歷會返回繼承的屬性,因此能夠經過設置 enumerable 屬性值爲 false 來讓其忽略該屬性
Object.getOwnPropertyDescriptor(Object.prototype, 'toString')
// ES7 引入了Object.getOwnPropertyDescriptors方法,
// 返回指定對象全部自身屬性(非繼承屬性)的描述對象
複製代碼
(1) for...in
循環遍歷對象自身的和繼承的可枚舉屬性(不包含Symbol屬性)
(2) Object.keys(obj)
返回一個數組,包含對象自身的全部屬性的(不含繼承)全部可枚舉屬性(不含Symbol屬性)的鍵名
(3) Object.getOwnPropertyNames(obj)
返回一個數組,包含對象自身的全部屬性(不含Symbol屬性,可是包括不可枚舉屬性)的鍵名
(4) Object.getOwnPropertySymbols(obj)
返回一個數組,包含對象自身的全部鍵名,無論鍵名時Symbol 或字符串,也無論是否可枚舉
(5) Reflect.ownKeys(obj)
返回一個數組,包含對象自身的全部鍵名,無論鍵名時Symbol或者字符串,也無論是否可枚舉
// 以上 5 種遍歷對象的鍵名都遵照一樣的屬性遍歷的次序規則
- 首先遍歷全部的數值鍵,按照數值升序排序
- 其次遍歷全部的字符串鍵,按照加入時間升序排列
- 最後遍歷全部訂單 Symbol 鍵,按加入時間升序排序
// 例:
Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
// ['2','10','b','a',Symbol()]
複製代碼
表示指向當前對象的原型對象
let obj = {
foo:123,
foo(){
return super.name;
}
};
Object.prototype.name="ybm";
console.log(obj.foo());
// 注意,此關鍵詞只能用於對象的方法中,在其餘地方使用會報錯
let obj = {
foo:super.name
}
// 報錯,該關鍵詞用於對象的屬性中
let obj = {
foo:()=>super.name
}
let obj = {
foo:function (){
return super.name;
}
}
// 報錯,由於在JS引擎的解析中,此時的super用在一個函數中,而後賦值給foo屬性。
// 因此,目前只有對象方法的簡寫形式可讓js引擎確認定義的是對象的方法
/* 在JS引擎的內部,super.foo等同於 Object.getPrototypeOf(this).foo 屬性 或 Object.getPrototypeOf(this).foo.call(this) 方法 */
複製代碼
// 比較兩個值是否相等 可比較特殊的字符
Object.is(NaN,NaN) // true
Object.is(+0,-0) // false
Object.is({},{}) // false
Object.is(+0,0) // true
Object.is(-0,0) // false
複製代碼
// 用於的對象的合併,將源對象的全部可枚舉的屬性複製到目標對象中,不拷貝繼承迭代屬性
// 若屬性名相同,則後面對象的屬性值會覆蓋前面的屬性值
Object.assign(目標對象,源對象)
const target = {a:1};
const target1 = {b:2};
const target2 = {c:3};
const target3 = {a:4};
Object.assign(target,target1,target2,target3)
// target {a:4,b:2,c:3};
// 第二個參數能夠爲一個字符串,若是是字符串,就會以數組的形式拷貝進目標的對象
// 數值和布爾類型則不會起做用
let str = "abc";
let obj = {a:1};
Object.assign(obj,str);
// obj {'0':'a', '1':'b', '2':'c', a:1}
// 1. 爲對象添加方法
Object.assign(SomeClass.prototype,{
someMethod(a,b){
},
anotherMethod(){
}
})
// 等同於下面的寫法
SomeClass.prototype.someMethod = function(a,b){};
someClass.prototype.anotherMethod = function(){};
// 2. 拷貝對象
function clone(obj){
return Object.assign({},obj);
// 此方法只能拷貝自身的值,不能拷貝繼承的值
}
// 3. 合併多個對象
const merge = (target,...sources) => Object.assign(target,...sources);
複製代碼
// 返回指定對象全部自身屬性(非繼承屬性)的描述對象
const obj = {
foo:123,
get bar(){return 'abc'}
};
Object.getOwnPropertyDescriptors(obj);
// { foo:
// { value: 123,
// writable: true,
// enumerable: true,
// configurable: true },
// bar:
// { get: [Function: get bar],
// set: undefined,
// enumerable: true,
// configurable: true } }
複製代碼
// 建立一個新對象,並指定新對象的 __proto__ 指向
// 語法 Object.create(proto); 第一個參數爲新對象的原型指向
let obj1 = {a:1};
let obj2 = Object.create(obj);
obj2.a; // 1
複製代碼
// 設置指定對象的原型對象,並返回當前對象
// 語法:Object.setPrototypeOf(object,prototype);
let obj1 = {a:1};
let obj2 = {b:2};
Object.setPrototypeOf(obj1, obj2);
obj1.b; // 2
複製代碼
// 返回指定對象的原型對象
let obj = Object,getPrototypeOf(obj1);
obj {b:2};
複製代碼
// Object.keys(obj)
// 返回一個數組,成員是參數對象自身的(不含繼承的)全部可遍歷屬性的鍵名
var obj = {foo:'bar',baz:44};
var arr = Object.kes(obj);
arr ['foo','baz'];
// Object.values()
// 返回一個數組,成員是參數對象自身的(不含繼承的)全部可遍歷屬性的屬性值
var obj = {a:1,b:2};
var arr = Object.values(obj);
arr [1,2];
// Object.entries() 不支持IE
// 返回一個二維數組,每個數組項是參數對象自身的(不含繼承的)全部可遍歷屬性
// 的鍵值對造成的數組,忽略 Symbol
var obj = {a:1,b:2};
var arr = Object.entries(obj);
arr [['a',1],['b',2]]
複製代碼
// Object.fromEntries() 方法是 Object.entries() 的逆操做,
// 用於將一個鍵值對數組轉換成一個鍵值對形式的對象
// 注:只兼容火狐瀏覽器
Object.fromEntries([
['foo', 'bar'],
['baz', 42]
])
// { foo: "bar", baz: 42 }
複製代碼
/* 1. Symbol 值經過 Symbol()函數生成 2. Symbol 函數能夠接受一個字符串做爲參數,表示對Symbol實例的描述 3. Symbol 能夠顯式轉換成字符串,布爾值,但不能轉換成數字 */
let si = Symbol('foo')
console.log(si)// Symbol(foo)
/*用法?*/
let abc = Symbol('abc');
let obj = {
[abc]:'456',
'abc':'457',
}
複製代碼
new Set() 生成的是Set的數據結構,其結構內不會有重複的值,是一個類數組對象
內部判斷兩個值是否相同使用的算法叫作「Same-value-zero equality」,相似於 === 比較,可是該算法中 NaN與NaN相等
let arr = [1,1,2,2,3,3]
const a = new Set();
arr.forEach(x=>a.add(x));
for(let i of a){
console.log(i)
}//1 2 3 4
//1. Set函數能夠接受一個數組或具備iterable接口的其餘數據結構做爲參數
例一:數組爲參數
const set = new Set([1,2,3,4,5,6]);
[...set] // [1,2,3,4,5,6]
例二:具備iterable接口的僞數組做爲參數
const set = new Set(document.querySelectorAll('div'));
set.size; // 110
//2. 數組去重
var arr = [1,2,3,1,1,2,3,4];
[...new Set(arr)]; // [1,2,3,4]
//3. 字符串去重
var str = '123132451234561321';
[...new Set(str)].join(''); // "123456"
//4. NaN
var [a,b] = [NaN,NaN];
let set = new Set();
set.add(a);set.add(b);
[...set]; // [NaN]
//5. 並集,交集,差集
let a = new Set([1,2,3]);
let b = new Set([2,3,4]);
// 並集
[...new Set(...a,...b)]; //[1,2,3,4]
// 交集
[...new Set([...a].filter(x=>b.has(x)))]; //[2,3]
// 差集
[...new Set([...a].filter(x=>!b.has(x)))]; //[1]
// Set 結構的實例屬性
Set.prototype.constructor :構造函數,默認就是Set函數
Set.prototype.size :返回 Set 實例的成員總數
// Set 結構的實例方法
// 1> 操做方法
.add(value) :添加某個值,返回Set結構自己
.delete(value) :刪除某個值,返回一個布爾值,表示刪除是否成功
.has(value) :判斷是否存在這個值,返回一個布爾值
.clear() :清除全部的成員,無返回值
// 2> 遍歷方法、
.keys() :返回鍵名的遍歷器
.value() :返回鍵值的遍歷器
.entries() :返回鍵值對的遍歷器
.forEach() ;使用回調函數遍歷每一個成員
// 因爲 Set 結構沒有鍵名(或者說鍵名和鍵值是同樣的),因此keys() 和 values() 方法獲得的結果同樣
var arr = [1,2,3];
let set = new Set();
for (let item of set.entries()) {
console.log(item); // [1,1] [2,2] [3,3]
}
// Set 結構的實例默認是可遍歷的,默認遍歷器生成函數就是它的values方法
// 因此能夠直接省略values方法,直接用 for...of遍歷
for (let item of set) {
console.log(item); // 1 2 3
}
複製代碼
1. 與Set相似,也是不重複的值的集合,可是WeakSet的成員只能是對象 2. WeakSet爲弱引用,即:垃圾回收機制不計算WeakSet對該對象的引用次數。因此,WeakSet適合存儲一些臨時數組,當該數組在外部引用此時爲0時,他在WeakSet中的引用就會自動消失 3. 因爲成員是弱引用,隨時會消失,因此ES6規定WeakSet不可遍歷 4. 該構造函數能夠接受一個數組,或者一個類數組(具備 Iterable 接口)對象,該數組的成員會自動轉換成WeakSet實例對象的成員
// WeakSet結構的三個方法
-WeakSet.prototype.add(value);
-WeakSet.prototype.delete(value);
-WeakSet.prototype.has(value);
let arr = [[1,2],[2,3]];
var weak = new WeakSet(arr);
// {[1,2],[2,3]}
複製代碼
1. js對象本質上是鍵值對的集合,可是傳統上只能用字符串做爲鍵,因此限制性大,所以ES6提供了一種新的數據結構,相似對象,也是一個鍵值對的集合,但鍵名能夠是任意類型
// 實例的屬性和操做方法
.size //放回Map結構的成員總數
.set(key,value) //添加或者更新一組鍵值對,返回整個Map數據結構
.get(key) //返回指定鍵的值,若不存在,則返回undefined
.has(key) //判斷是否存在指定鍵,返回布爾值
.delete(key) //刪除指定鍵
.clear(key) //刪除全部的鍵,無返回值
// 遍歷方法---遍歷順序就是插入順序
keys():返回鍵名的遍歷器。
values():返回鍵值的遍歷器。
entries():返回全部成員的遍歷器。
forEach():遍歷 Map 的全部成員。
// 默認的遍歷器接口爲entries()
// 1. 基本使用方法
let map = new Map();
let m = {a:'1'};
map.set(m, 'content');
map.get(m); // content;
map.has(m); // true;
map.delete(m); // true;
map.has(m); // false
// 2. 能夠接受一個雙成員的二維數組,或者具備Iterable接口,且每一個成員都是一個雙元素的類數組對象做爲參數
let map2 = new Map([['a',1],['b',10]]);
map2.get('a'); // 1
map2.get('b'); // 10
// 使用Set 和 Map 實例做爲參數
const set = new Set([
['foo', 1],
['bar', 2]
]);
const m1 = new Map(set);
m1.get('foo') // 1
const m2 = new Map([['baz', 3]]);
const m3 = new Map(m2);
m3.get('baz') // 3
// 3. 讀取一個未知鍵,則返回undefined
new Map().get('a'); // undefined
// 4. 在Map中 NaN與NaN相等
let mp = new Map();
mp.set(NaN,'1');
mp.set(NaN,'2');
mp.get(NaN); // 2
複製代碼
WeakMap結構與Map結構相同,也是用於生成鍵值對的集合 1. 只接受鍵名做爲鍵名,2. 鍵名所對應的值不計入垃圾回收機制
// 通常用於對象在未來會消失,這樣這個對象所對應的鍵值也會被回收,不須要手動回收
let myElement = document.getElementById('logo');
let myWeakmap = new WeakMap();
myWeakmap.set(myElement, {timesClicked: 0});
myElement.addEventListener('click', function() {
let logoData = myWeakmap.get(myElement);
logoData.timesClicked++;
}, false);
// 當DOM元素被刪除時,WeakMap中該對象所對應的鍵值對也會自動刪除
// 操做方法
.set()
.get()
.has()
.delete()
複製代碼
一種異步解決的方案,一個容器,保存着將來某個時間段某個異步操做的結果
特色: 1. promise對象的狀態不受外界所改變,它表明着一種異步操做,有三種狀態:pending(進行中),fulfilled(成功),rejected(失敗),只有結果才能獲取是哪種狀態 2. 狀態一旦改變一次,就不可再次更改,狀態改變只有兩種:pending--fulfilled,pending--rejected。只要這兩種情況發生,狀態就定型了,這是就稱爲resolved(已定型)
缺點 1. 沒法取消,一旦新建就會當即執行,沒法中途取消 2. 若是不設置回調函數,promise內部出現的錯誤不會反應到外部 3. 當處於pending狀態時,不知道目標是處於那一階段(剛開始or已完成)
// 基本使用:
const promise = new Promise(function(resolve, reject){
// 異步代碼...
if('異步成功時'){
resolve();//成功的回調函數調用
}else{
reject();//失敗的回調函數調用
}
})
promise.then(callback1,callback2);
//.then()方法用於綁定該對象結果的兩個階段所對應的回調函數
//.then()方法會在當前腳本全部同步任務執行完後纔會執行
//若是第一個.then()方法中返回的是一個promise對象,
// 那麼第二個.then()方法會等待第一個的狀態改變時再來判斷是否執行
promise.then().catch(callback)
//.catch()方法:當異步操做拋出錯誤或者回調函數運行出錯時會被被該方法捕獲
//若是promise的狀態已經爲成功狀態,那麼再拋出異常就會無效
複製代碼
// 用於指定無論promise對象最後的狀態如何,都會執行的操做
promise.then(result => {...})
.catch(error => {...})
.finally(()=>{...})
// 本質是then()方法的特例,等同於
.then(result => {},error => {}) //成功或者失敗的方法各寫一遍
// 例:請求完後關閉服務器
promise.then().finally(server.stop);
複製代碼
// 用於將多個Promise實例,包裝成一個新的Promise實例,並返回
const p = Promise.all([p1, p2, p3]);
/* 接受一個數組做爲參數,數組中的每個成員都是一個Promise實例 p的狀態由 p1,p2,p3決定, 當3個都爲fulfilled時,p的狀態才爲fulfilled,此時p1,p2,p3的返回值會組成一個數組傳遞給p的回調函數 當其中一個爲reject時,p的狀態爲rejected,此時第一個rejected狀態的實例的返回值會傳遞給p的回調函數 注意:若做爲參數的promise實例本身定義了catch方法,那麼就不會觸發Promise.all()所定義的catch() */
複製代碼
// 用於將多個Promise實例,包裝成一個新的Promise實例
const p = Promise.race([p1, p2, p3]);
/* 接受一個數組做爲參數,數組中的每個成員都是一個Promise實例 當參數中某個Promise實例的狀態率先發生改變時,p的狀態也會發生改變,率先改變的返回值會傳遞給p的回調函數 */
// 指定時間內沒有得到結構就返回rejected
var p = Promise.race([p1,
new Promise((res,error)=>{
setTimeout(()=>{error();},5000);
})]);
p.then().catch(); // 第一個參數5秒內沒有執行成功就拋出失敗
複製代碼
將現有對象轉換成一個Promise對象
const ps = Promise.resolve(對象)
// 當參數是一個thenable對象,即:具備then()方法的對象時,轉換完後會當即執行該方法
// 當參數不是具備then()方法的對象,或根本不是一個對象時,該方法會自動生成一個新的Promise對象,狀態爲
// 成功狀態,並把參數傳遞給相對應的對調函數
// 當無參數時,該方法會自動建立一個新的Promise對象,狀態爲成功狀態
複製代碼
返回一個新Promise實例,狀態爲rejected,並當即執行回調函數
//注:與resolve()不一樣的是reject()方法會把建立時的參數原封不動的傳遞給回調函數
複製代碼
爲了方便無論是同步仍是異步都用promise管理代碼
是一種接口,爲不一樣的數據結構提供一種統一的訪問機制,任何數據只要部署了Iterator接口均可以完成遍歷操做
遍歷過程:
ES6 規定,默認的 Iterator 接口部署在數據結構的Symbol.iterator
屬性,這個屬性是一個函數表達式,執行它就會返回一個遍歷器 for...of循環會調用Symbol.iterator屬性,返回返回對象中的value值
// 模擬next()方法
function makeIterator(obj){
let nextIndex = 0;
return {
next:()=>{
return nextIndex < obj.length ?
{value:obj[nextIndex++], done:false}:
{value:undefined, done:true}
}
}
}
var arr = [1,2,3];
var obj = makeIterator(arr);
obj.next(); //{value:1}
obj.next(); //{value:2}
obj.next(); //{value:3}
obj.next(); //{done:true}
複製代碼
Array
Map
Set
String
TypedArray
函數的 arguments 對象
NodeList 對象(相似數組的對象)
// 例:調用數組的 Symbol.iterator屬性
var arr = [1,2]
var iter = arr[Symbol.iterator]()
// Symnol值要用[]括起來
iter.next(); // {value:1, done:false}
iter.next(); // {value:1, done:false}
iter.next(); // {value:undefined, done:false}
複製代碼
1. 解構賦值
var arr = new Set().add(1).add(2).add(3)
var [x,y] = arr // x:1 y:2
var [first,...rest] = arr //first:1 rest:[2,3]
2. 擴展運算符
var arr = "hello"
[...arr] // ['h','l','l','o']
3. 特殊的類數組對象:
例:querySelectorAll()
例:
var arrayLike1 = {
0: 'a',
1: 'b',
length: 2,
[Symbol.iterator]: Array.prototype[Symbol.iterator]
// 須要具備Symbol.iterator屬性
};
// 報錯
for (let x of arrayLike1) {
console.log(x);
}
複製代碼
-for...of
-Array.from()
-Map(),Set(),WeakMap(),WeakSet()
-Promise.all()
-Promise.race()
複製代碼
/* 遍歷器除了具備next()方法,還具備return()方法和throw()方法 當for...of循環提早退出(出錯時 或 break語句),就會調用 return 方法 注意:return方法必須返回一個對象,這是Generator規格規定 */
function readLinesSync(file) {
return {
[Symbol.iterator]() {
return {
next() {
return { done: false };
},
return() {
file.close();
return { done: true };
}
};
},
};
}
// 狀況一
for (let line of readLinesSync(fileName)) {
console.log(line);
break;
}
/* 當執行break方法後就會執行遍歷器的return()方法 */
// 狀況二
for (let line of readLinesSync(fileName)) {
console.log(line);
throw new Error();
}
/* 狀況二在執行return方法關閉文件以後,再拋出錯誤 */
複製代碼
// 1. function關鍵字與函數名的中間用 * 號鏈接
// 2. 函數體內部用 yield 表達式來表示不一樣的狀態
// 3. 調用Generator函數後返回一個遍歷器對象,即:指針對象,注:此時Generator函數內部代碼尚未執行
// 4. 遍歷器對象使用.next()方法進行執行函數體代碼,直到遇到 yield 表達式 或 return 語句中止
// 5. 遇到yield表達式時next()方法返回一個對象,{value:當前yield表達式的值, done:布爾值(當前遍歷的狀態)}
// 6. yield 關鍵字至關於一個暫停符,.next()方法就爲恢復執行
// 7. 返回的遍歷器對象不是this對象
// 8. 遍歷器對象能夠調用函數原型上的方法
function* hello(){
console.log(1)
field 'a'
console.log(2)
field 'b'
console.log(3)
return 'c'+'d'
console.log(4)
}
var hl = hello()
hl.next() // 1 {value:a, done:false}
hl.next() // 2 {value:b, done:false}
hl.next() // 3 {value:cd, done:true} 遇到return時 done的值就爲 true
hl.next() // {value:undefined, done:true} // 由於上一句已經return了,因此4不會被輸出
複製代碼
// 1. yield 表達式自己是沒有返回值的,或者說老是undefined
// 2. next()方法能夠帶一個參數,該參數就會被看成上一個yield表達式的返回值
// 3. 所以第一個調用.next()方法裏面傳參是無效的,V8引擎會直接忽略第一次調用的參數
// 4. 調用函數後需調用一次next()方法來啓動Generator函數的內部代碼
function* f() {
for(var i = 0; true; i++) {
var reset = yield i;
if(reset) { i = -1; }
}
}
var g = f();
g.next() // { value: 0, done: false }
g.next() // { value: 1, done: false }
g.next() // { value: 2, done: false }
g.next(true) // { value: 0, done: false }
// 前三次執行時,reset爲undefined,第四次執行時,next()方法傳了一個參數true,
// 因此yield表達式的,返回值就爲true,i=1,i++就爲0
// 此特性能夠在特定階段從函數外部向內部傳入值
function* foo(x) {
var y = 2 * (yield (x + 1));
var z = yield (y / 3);
return (x + y + z);
}
var b = foo(5);
b.next() // { value:6, done:false }
b.next(12) // { value:8, done:false }
b.next(13) // { value:42, done:true }
複製代碼
// for ... of 循環能夠自動遍歷Generator函數時所生成的iterator對象
// ----------------------------------------------------------
for in // 遍歷的是數組的索引--即鍵名
---遍歷時會包括數組的原型屬性和方法,因此通常用來遍歷對象而不是數組
---用 arr.hasOwnPropery(屬性) 方法可判斷該屬性是否是該對象的實例屬性
---數組的鍵名是數字時,for..in循環會轉換成字符串獲取
---某些狀況下,遍歷順序是任意的
for of // 遍歷的是數組的元素值
---遍歷時不包括數組的原型屬性和方法
---遍歷數組時只返回具備數字屬性的值
// 例:實現斐波那鍥數列
function* fbnq(){
let [a,b] = [0,1]
for(;;){
yield b
[a,b] = [b,a+b]
}
}
for(var n of fbnq()){
if(n>1000) break
console.log(n)
}
複製代碼
// 調用遍歷器對象的return()方法後返回對象中的value值就是return()方法的參數,而且done的值爲true
// 此時,Generator函數的遍歷就會中止,若是無參數,則value值爲undefined
function* gen() {
yield 1;
yield 2;
yield 3;
}
var g = gen();
g.next() // { value: 1, done: false }
g.return('foo') // { value: "foo", done: true }
g.next() // { value: undefined, done: true }
複製代碼
// 用於在一個Generator函數中調用另一個Generator函數
// yield* 表示返回的是一個遍歷器對象,若不加js不會自動識別,會輸出這個對象
// 無 return 語句時
function* foo(){
yield 'a'
yield 'b'
}
function* bar(){
yield 'x'
yield* foo()
yield 'y'
}
for(let n of bar()){
console.log(n) // 'x' 'a' 'b' 'y'
}
// 有 return 語句時,能夠用一個變量來接收 field* foo 表達式的返回值
function* foo(){
yield 'a'
yield 'b'
return 'c'
}
function* bar(){
yield 'x'
let a = field* foo()
console.log(a)
yield 'y'
}
for(let n of bar()){
console.log(n) // 'x' 'a' 'b' 'c'y'
}
// 例:利用yield* 命令遍歷取出二維數組
function* iterTree(tree) {
if (Array.isArray(tree)) {
for(let i=0; i < tree.length; i++) {
yield* iterTree(tree[i]);
}
} else {
yield tree;
}
}
const tree = [ 'a', ['b', 'c'], ['d', 'e'] ];
for(let x of iterTree(tree)) {
console.log(x);
}
or [...iterTree(tree)]
複製代碼
let obj = {
* myGeneratorMethod(){} // myGeneratorMethod: function* (){}
}
複製代碼
var clock = function* () {
while (true) {
console.log('Tick!');
yield;
console.log('Tock!');
yield;
}
};
複製代碼
// 傳值調用:參數爲表達式時,表達式在進入函數體以前就已經計算完成
// 傳名調用:參數爲表達式時,表達式只有在函數體中使用到時才進行計算
Thunk 函數的定義:將一個參數放到一個臨時函數內,再把臨時函數當參數傳入函數體中,
這個臨時函數就是Thunk函數
複製代碼
// 1. 語法與 Generator 函數類似
var asyncRead = async function(){
const f1 = await f1()
}
// 1. 返回一個promise對象
// 2. 有兩個關鍵字 async await 分別對應 * yield
// 3. async 函數內置執行器,即:不須要像Generator函數須要.next()方法執行
// 4. await命令後面能夠是promise對象和原始數據類型(可是這時會當即自動轉換成resolved 的 promise對象)
// 5. async函數內部return 語句返回的值會成爲then方法回調函數的參數
// 6. async函數內部拋出錯誤會直接返回的Promise對象的變成reject狀態,而後被catch捕獲
// 7. 當遇到第一個await時,後面的代碼都會被放入隊列中執行
// 8. 只有當await後面的promise對象執行完後,他的狀態纔會改變
// 9. 只用當async函數內部的全部異步操做執行完後纔會執行then方法
// 10 若將異步操做放到try...catch裏面,則該異步操做不管是否成功,後面的異步操做都會繼續執行
複製代碼
// 1. 順序觸發
async function myFunction() {
await getFoo()
await getBar()
} // 只用getFoo()執行完後 getBar()纔會執行
// 2. 同時觸發
async function myFunction() {
var fooPromise = getFoo()
var barPromise = getBar()
await fooPromise
await barPromise
// 此時就至關於兩個異步函數的執行結果被await攔截了
}
async function myFunction() {
var [foo,bar] = await Promise.all([getFoo(),getBar()])
}
複製代碼
// Class 類的基本使用
class Point{
constructor() {
// 實例屬性
this.name = 2
}
// 原型對象上的實例方法
toString() {}
// 靜態屬性
static a = '41'
// 靜態方法
static show(){ }
}
var p = new Point()
p.toString()
// 1. 使用方法與構造函數相同
// 2. 方法之間不須要用逗號分隔
// 3. 類中的全部方法其實是定義在 類名的prototype上
即等同於:Point.prototype = {
constructor(){},
toString(){}
}
因此類的實例調用方法其實就是調用原型上的方法
// 4. 類中的全部的方法都是不可枚舉的
Object.keys(Point.prototype) //[]
// 5. 類沒有變量提高
// 類名錶達式
var cls = class Me{}
var cls = class {}
var cls = new class {} // 這樣就能夠直接調用class裏面的方法了
複製代碼
// 1. 每一個類在建立的時候必須有一個constructor()方法
// 2. 若是沒有顯示建立,則系統會默認建立一個
// 3. 該方法會在 new 命令後自動調用,默認返回實例對象,即:this,也能夠改寫此屬性,返回另外一個對象
class Point {
z = 0;
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ','this.z+')';
}
}
var p = new Point(1,2)
p.toString() // (1,2)
複製代碼
// 在類的內部經過 set get 關鍵字來攔截某個屬性的存取值的操做
// 調用時不能加括號,當表達式調用
class MyClass{
set prop(val){
this.val = val
console.log(this.val+'a')
}
get prop(){
console.log(this.val)
}
}
var myclass = new MyClass()
myclass.prop = 1 // 注意,此時沒有加小括號 '1a'
myclass.prop 1
複製代碼
// 繼承
class Bar{}
class aaa extends Bar {
constructor(){
super(); // 該關鍵詞的做用是調用父類的constructor方法,子類中必須寫,
// 不然建立實例時報錯---重寫constructor()時
// 做爲對象時表明指向父類的原型對象,在靜態方法中,指向父類
// 由於指向的是原型對象,因此父類上實例的屬性和方法,super訪問不到
// 經過super調用父類上方法中的this表明的是當前子類的實例
}
}
// super()當函數時使用
class A {
constructor(name,age){
this.name = name
this.age = age
}
say(){
console.log(this.name,this.age)
}
}
class B extends A{
constructor(...args){
super(...args) // 分配內存空間,指向this,同時將父類的屬性掛載到this上
// super時父類構造器的一個引用,調用super就是調用父類的構造函數
// super前不能使用this
}
}
const b = new B('xy', 18)
// super當對象時使用
class A {
p() {
return 2;
}
}
class B extends A {
constructor() {
super();
console.log(super.p()); // 2
}
}
let b = new B();
複製代碼
// name屬性
class Bar{}
Bar.name // 'Bar'
// this
class 中的 this 是指向當前實例 // static // 當一個方法名前加了static關鍵詞時,該方法就不會被實例所繼承,但能夠被他的 子類 繼承 class Bar{
static add(){this}
// 注意:其中的this是指類,而不是指實例
}
// 靜態屬性的定義
class Bar{
}
Bar.a = 1 //注意,寫在外面
複製代碼
// 該方法能夠從子類上獲取父類
Object.getPrototypeOf(子類名) === 父類名
// 能夠用該方法來判斷一個類是否繼承了另外一個類
複製代碼