['1', '2', '3'].map(parseInt)的結(jié)果是什么?
Answer函數(shù)參數(shù)對象
arguments與ES6新增的rest參數(shù)都是數(shù)組嗎?
Answer:arguments對象不是數(shù)組,而是一個類似數(shù)組的對象。所以為了使用數(shù)組的方法,需先使用Array.prototype.slice.call先將其轉(zhuǎn)為數(shù)組。rest 參數(shù)就不存在這個問題,它就是一個真正的數(shù)組,數(shù)組特有的方法都可以使用。箭頭函數(shù)有幾個使用注意點。
詳細(xì)資料
(1)函數(shù)體內(nèi)的this對象,就是定義時所在的對象,而不是使用時所在的對象。(
箭頭函數(shù)沒有 this,所以需要通過查找作用域鏈來確定 this 的值。這就意味著如果箭頭函數(shù)被非箭頭函數(shù)包含,this 綁定的就是最近一層非箭頭函數(shù)的 this。因為箭頭函數(shù)沒有 this,所以也不能用 call()、apply()、bind() 這些方法改變 this 的指向).
// ES6
function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}
// ES5
function foo() {
var _this = this;
setTimeout(function () {
console.log('id:', _this.id);
}, 100);
}
(2)不可以當(dāng)作構(gòu)造函數(shù),即不可以使用new命令,否則會拋出一個錯誤。也就沒有new.target、原型、super。
(3)沒有自己的 arguments 對象,可以用 rest 參數(shù)代替。但箭頭函數(shù)可以訪問外圍函數(shù)的 arguments 對象。
(4)不可以使用yield命令,因此箭頭函數(shù)不能用作 Generator 函數(shù)。
- super: 指向當(dāng)前對象的原型對象。super關(guān)鍵字表示原型對象時,只能用在對象的方法之中,用在其他地方都會報錯。(目前,只有對象方法的簡寫法可以讓 JavaScript 引擎確認(rèn),定義的是對象的方法。)
// 報錯
const obj = {
foo: super.foo
}
// 報錯
const obj = {
foo: () => super.foo
}
// 報錯
const obj = {
foo: function () {
return super.foo
}
}
// 正常
const proto = {
foo: 'hello'
};
const obj = {
foo: 'world',
find() {
return super.foo;
}
};
Object.setPrototypeOf(obj, proto);
obj.find() // "hello"
-
Object.assign: 將源對象(source)的所有可枚舉屬性(不包括繼承屬性),復(fù)制到目標(biāo)對象(target)。
特點:
(1)屬于淺拷貝:如果源對象某個屬性的值是對象,那么目標(biāo)對象拷貝得到的是這個對象的引用。
(2)同名屬性的替換。
const target = { a: { b: 'c', d: 'e' } }
const source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }
(3)對數(shù)組的處理:將數(shù)組視為對象。
Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]
Object.assign把數(shù)組視為屬性名為 0、1、2 的對象,因此源數(shù)組的 0 號屬性4覆蓋了目標(biāo)數(shù)組的 0 號屬性1。
(4) 取值函數(shù)的處理: Object.assign只能進(jìn)行值的復(fù)制,如果要復(fù)制的值是一個取值函數(shù),那么將求值后再復(fù)制。
const source = {
get foo() { return 1 }
};
const target = {};
Object.assign(target, source)
// { foo: 1 }
上面代碼中,source對象的foo屬性是一個取值函數(shù),Object.assign不會復(fù)制這個取值函數(shù),只會拿到值以后,將這個值復(fù)制過去。
用途:
(1)為對象添加屬性;
(2)為對象添加方法;
(3)克隆對象:將原始對象拷貝到一個空對象,就得到了原始對象的克隆。不過這樣不會克隆原始對象繼承的屬性。如果想要保持繼承鏈,可以采用下面的代碼。
function clone(origin) {
let originProto = Object.getPrototypeOf(origin);
return Object.assign(Object.create(originProto), origin);
}
(4)合并多個對象;
(5)為屬性指定默認(rèn)值。
-
Symbol:ES6新引入的一種原始數(shù)據(jù)類型,表示獨(dú)一無二的值。
詳細(xì)資料
let s=Symbol();
typeof s; // symbol
Symbol函數(shù)前不能使用new命令,這是因為生成的 Symbol 是一個原始類型的值,不是對象。由于 Symbol 值不是對象,所以不能添加屬性?;旧?,它是一種類似于字符串的數(shù)據(jù)類型。
-
js擴(kuò)展運(yùn)算符
...:ES6新增,內(nèi)部使用for...of循環(huán),可將一個數(shù)組(或數(shù)組類似結(jié)構(gòu))轉(zhuǎn)為用逗號分隔的序列。可用于:
(1)復(fù)制數(shù)組(對原數(shù)組無影響)
var a = ['1','2','3']
var b = [...a]
console.log(b) // ['1','2','3']
(2)拼接數(shù)組
var a = [1,2,3]
var a = [4,5,6]
a = [...a, ...b]
console.log(a) // [1,2,3,4,5,6]
(3)便于使用Math方法獲取數(shù)組最大最小值
var a = [1,2,3,4,5]
var max = Math.max(...a)
console.log(max) // 5
(4)字符串轉(zhuǎn)換為字符數(shù)組
var a = 'helloworld'
var b = [...a]
console.log(b) // ['h','e','l','l','o','w','o','r','l','d']
8-1. Set:字面意思就是集合,ES6新增的數(shù)據(jù)結(jié)構(gòu),類似于數(shù)組,但其中的元素不重復(fù)。
(1)可利用Set去除數(shù)組的重復(fù)元素:
[...new Set(array)]
// or
Array.from(new Set(array));
(2)可利用Set去除字符串中的重復(fù)字符:
[...new Set('abbccd')].join(''); // 'abcd'
(3)求集合的并集、交集、差集
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 并集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// 差集
let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}
8-2: WeakSet, Map, WeakMap:詳細(xì)介紹
WeakSet 和 WeakMap 相比較對于的Set和Map,不同點:(1)成員(for Set)或鍵名(for Map)都只能是對象;
(2)成員或鍵名所引用的對象都是弱引用,即垃圾回收機(jī)制不將該引用考慮在內(nèi)。因此,只要所引用的對象的其他引用都被清除,垃圾回收機(jī)制就會釋放該對象所占用的內(nèi)存。也就是說,一旦不再需要,(WeakSet)WeakMap 里面的鍵名對象和所對應(yīng)的鍵值對會自動消失,不用手動刪除引用,WeakMap的專用場合就是,它的鍵所對應(yīng)的對象,可能會在將來消失。WeakMap結(jié)構(gòu)有助于防止內(nèi)存泄漏。.
一個典型應(yīng)用場景是,在網(wǎng)頁的 DOM 元素上添加數(shù)據(jù)(例如說明性的信息),就可以使用WeakMap結(jié)構(gòu)。當(dāng)該 DOM 元素被清除,其所對應(yīng)的WeakMap記錄就會自動被移除。
const wm = new WeakMap();
const element = document.getElementById('example');
wm.set(element, 'some information');
wm.get(element) // "some information"
上面的 DOM 節(jié)點對象 element 的引用計數(shù)是1,而不是2。這時,一旦消除對該節(jié)點的引用,它占用的內(nèi)存就會被垃圾回收機(jī)制釋放。Weakmap 保存的這個鍵值對,也會自動消失。
注意,WeakMap 弱引用的只是鍵名,而不是鍵值。鍵值依然是正常引用。
const wm = new WeakMap();
let key = {};
let obj = {foo: 1};
wm.set(key, obj);
obj = null;
wm.get(key); // Object {foo: 1}
上面代碼中,鍵值obj是正常引用。所以,即使在 WeakMap 外部消除了obj的引用,WeakMap 內(nèi)部的引用依然存在。
-
Proxy:可以理解成,在目標(biāo)對象之前架設(shè)一層“攔截”,外界對該對象的訪問,都必須先通過這層攔截,因此提供了一種機(jī)制,可以對外界的訪問進(jìn)行過濾和改寫。Proxy 這個詞的原意是代理,用在這里表示由它來“代理”某些操作,可以譯為“代理器”。
Proxy 對象可以攔截目標(biāo)對象的任意屬性,這使得它很合適用來寫 Web 服務(wù)的客戶端。
this問題:雖然 Proxy 可以代理針對目標(biāo)對象的訪問,但它不是目標(biāo)對象的透明代理,即不做任何攔截的情況下,也無法保證與目標(biāo)對象的行為一致。主要原因就是在 Proxy 代理的情況下,目標(biāo)對象內(nèi)部的this關(guān)鍵字會指向 Proxy 代理。
const target = {
m: function () {
console.log(this === proxy);
}
};
const handler = {};
const proxy = new Proxy(target, handler);
target.m() // false
proxy.m() // true
10.Reflect:詳細(xì)介紹
Reflect對象與Proxy對象一樣,也是 ES6 為了操作對象而提供的新 API。
(1) 將Object對象的一些明顯屬于語言內(nèi)部的方法(比如Object.defineProperty),放到Reflect對象上。)
(2) 修改某些Object方法的返回結(jié)果,讓其變得更合理。
(3) 讓Object操作都變成函數(shù)行為。某些Object操作是命令式,比如name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)讓它們變成了函數(shù)行為。
(4)Reflect對象的方法與Proxy對象的方法一一對應(yīng),只要是Proxy對象的方法,就能在Reflect對象上找到對應(yīng)的方法。這就讓Proxy對象可以方便地調(diào)用對應(yīng)的Reflect方法,完成默認(rèn)行為,作為修改行為的基礎(chǔ)。也就是說,不管Proxy怎么修改默認(rèn)行為,你總可以在Reflect上獲取默認(rèn)行為。
Note:Reflect.apply方法等同于Function.prototype.apply.call(func, thisArg, args),用于綁定this對象后執(zhí)行給定函數(shù)。
一般來說,如果要綁定一個函數(shù)的this對象,可以這樣寫fn.apply(obj, args),但是如果函數(shù)定義了自己的 apply 方法,就只能寫成Function.prototype.apply.call(fn, obj, args),采用Reflect對象可以簡化這種操作。
利用 Proxy 和 Reflect 實現(xiàn)觀察者模式:
觀察者模式(Observer mode)指的是函數(shù)自動觀察數(shù)據(jù)對象,一旦對象有變化,函數(shù)就會自動執(zhí)行。
下面,使用 Proxy 寫一個觀察者模式的最簡單實現(xiàn),即實現(xiàn)observable和observe這兩個函數(shù)。思路是observable函數(shù)返回一個原始對象的 Proxy 代理,攔截賦值操作,觸發(fā)充當(dāng)觀察者的各個函數(shù)。
const queuedObservers = new Set();
const observe = fn => queuedObservers.add(fn);
const observable = obj => new Proxy(obj, {set});
function set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
queuedObservers.forEach(observer => observer());
return result;
}
上面代碼中,先定義了一個Set集合,所有觀察者函數(shù)都放進(jìn)這個集合。然后,observable函數(shù)返回原始對象的代理,攔截賦值操作。攔截函數(shù)set之中,會自動執(zhí)行所有觀察者。
11.Promise:詳細(xì)資料
簡單說就是一個容器,里面保存著某個未來才會結(jié)束的事件(通常是一個異步操作)的結(jié)果。從語法上說,Promise 是一個對象,通過它可以獲取異步操作的消息。(Promise一旦新建后就會立即執(zhí)行)。
特點:
(1)Promise對象的狀態(tài)不受外界影響。Promise對象代表一個異步操作,有三種狀態(tài):pending(進(jìn)行中)、fulfilled(已成功)和rejected(已失敗)。只有異步操作的結(jié)果,可以決定當(dāng)前是哪一種狀態(tài)。
(2)一旦狀態(tài)改變,就不會再變,任何時候都可以得到這個結(jié)果。Promise對象的狀態(tài)改變,只有兩種可能:從pending變?yōu)閒ulfilled和從pending變?yōu)閞ejected。只要這兩種情況發(fā)生,狀態(tài)就凝固了,不會再變了,會一直保持這個結(jié)果,這時就稱為 resolved(已定型)。
有了Promise對象,就可以將異步操作以同步操作的流程表達(dá)出來,避免了層層嵌套的回調(diào)函數(shù)。
缺點:
(1)無法取消Promise,一旦新建它就會立即執(zhí)行,無法中途取消。
(2)如果不設(shè)置回調(diào)函數(shù),Promise內(nèi)部拋出的錯誤,不會反應(yīng)到外部。
(3)當(dāng)處于pending狀態(tài)時,無法得知具體進(jìn)度信息(剛剛開始還是即將完成)。
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi!');
// Promise
// Hi!
// resolved
上面代碼中,Promise 新建后立即執(zhí)行,所以首先輸出的是Promise。然后,then方法指定的回調(diào)函數(shù),將在當(dāng)前腳本所有同步任務(wù)執(zhí)行完才會執(zhí)行,所以resolved最后輸出。
then: then方法定義在原型對象Promise.prototype上,它的作用是為 Promise 實例添加狀態(tài)改變時的回調(diào)函數(shù)。
then方法返回的是一個新的Promise實例(注意,不是原來那個Promise實例)。因此可以采用鏈?zhǔn)綄懛?,即then方法后面再調(diào)用另一個then方法。
catch:是 then(null, rejection) 或 then(undefined, rejection) 的別名,用于指定發(fā)生錯誤時的回調(diào)函數(shù)。
(1)Promise 對象的錯誤具有“冒泡”性質(zhì),會一直向后傳遞,直到被catch語句捕獲為止。(在有 catch 的前提下,如果沒有catch,錯誤不會被捕獲,也不會傳遞到外層。因為Promise 內(nèi)部的錯誤不會影響到 Promise 外部的代碼,通俗的說法就是“Promise 會吃掉錯誤”。)
(2)一般來說,不要在then方法里面定義 Reject 狀態(tài)的回調(diào)函數(shù)(即then的第二個參數(shù)),總是使用catch方法。
(3)catch方法返回的還是一個 Promise 對象,因此后面還可以接著調(diào)用then方法。(而且catch方法之中,還能再拋出錯誤。)
-
排序算法穩(wěn)定性:不穩(wěn)定:快選堆希
穩(wěn) 定:插冒歸基
13.iterator:詳細(xì)介紹
它是一種接口,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的訪問機(jī)制。任何數(shù)據(jù)結(jié)構(gòu)只要部署 Iterator 接口,就可以完成遍歷操作(即依次處理該數(shù)據(jù)結(jié)構(gòu)的所有成員)。
作用:
(1)為各種數(shù)據(jù)結(jié)構(gòu),提供一個統(tǒng)一的、簡便的訪問接口;
(2)使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列;
(3) ES6 創(chuàng)造了一種新的遍歷命令for...of循環(huán),Iterator 接口主要供for...of消費(fèi)。
Iterator 的遍歷過程是這樣的。
(1)創(chuàng)建一個指針對象,指向當(dāng)前數(shù)據(jù)結(jié)構(gòu)的起始位置。也就是說,遍歷器對象本質(zhì)上,就是一個指針對象。
(2)第一次調(diào)用指針對象的next方法,可以將指針指向數(shù)據(jù)結(jié)構(gòu)的第一個成員。
(3)第二次調(diào)用指針對象的next方法,指針就指向數(shù)據(jù)結(jié)構(gòu)的第二個成員。
(4)不斷調(diào)用指針對象的next方法,直到它指向數(shù)據(jù)結(jié)構(gòu)的結(jié)束位置。
原生具備 Iterator 接口的數(shù)據(jù)結(jié)構(gòu)如下:
Array Map Set String TypedArray 函數(shù)的 arguments 對象
NodeList 對象
(除了Array、Map、Set,其他的都屬于類數(shù)組結(jié)構(gòu)(所謂類數(shù)組,就是存在數(shù)值鍵名和 length屬性))。
只要某個數(shù)據(jù)結(jié)構(gòu)部署了 Iterator 接口,就可以對它使用擴(kuò)展運(yùn)算符,將其轉(zhuǎn)為數(shù)組。
http常見簡單例子:
(1)輸入URL打開網(wǎng)頁;
(2)AJAX獲取數(shù)據(jù);
(3)img標(biāo)簽加載圖片;數(shù)組的reduce方法:縮小方法,接收兩個參數(shù),一個在每一個數(shù)組元素上調(diào)用的函數(shù),一個(可選的)作為縮小基礎(chǔ)的初始值。第一個參數(shù)是一個函數(shù),它有4個參數(shù):前一個值(prev),當(dāng)前值(cur),當(dāng)前項的索引,數(shù)組對象。這個函數(shù)的返回值會作為下一項的 prev。
如果指定了 reduce 方法中作為縮小基礎(chǔ)的第二個參數(shù)(init),即初始值,那么第一次迭代發(fā)生在數(shù)組第一項上,即 prev=init, cur=arr[0].
否則,第一次迭代發(fā)生在數(shù)組第二項上,即 prev=arr[0], cur=arr[1].