1. 程式人生 > 其它 >Web前端經典面試題-JavaScript

Web前端經典面試題-JavaScript

技術標籤:【JavaScript】面試前端html5css3javascript

Web前端經典面試題-JavaScript
看看銀行卡餘額,看看工資條,看看房價,動力就來了,大二狗,加油~~
JavaScript
原型鏈、類、繼承、作用域、閉包、js執行機制/單執行緒、js資料型別、js內建函式、內建物件、js去重、js邏輯判斷、js記憶體洩漏、dom、bom、通訊、ajax、錯誤監控、js基礎
一、原型鏈
1.1,建立物件有幾種方法?
1、字面量物件 // 預設這個物件的原型鏈指向object

var o1 = {name: '01'};

2、通過new Object宣告一個物件

var o11 = new Object(
{name: '011'});

3、使用顯式的建構函式建立物件

var M = function(){this.name='o2'};
var o2 = new M();
o2.__proto__=== M.prototype

o2的建構函式是M
o2這個普通函式,是M這個建構函式的例項
4、object.create()

var P = {name:'o3'};
var o3 = Object.create(P);
  • 原型、建構函式、例項、原型鏈

1、Object.prototype屬性是整個原型鏈的頂端
2、原型鏈通過prototype原型和proto屬性來查詢的.
3、所有的引用型別(陣列、物件、函式),都具有物件特性,即可自由擴充套件屬性(除了“null”以

外)。
4、所有的引用型別(陣列、物件、函式),都有一個proto屬性,屬性值是一個普通的物件(null除
外)。
5、所有的函式,都有prototype屬性,屬性值也是一個普通的物件。
6、所有的引用型別(陣列、物件、函式),proto屬性指向它的建構函式prototype屬性值
7、例項本身的屬性和方法如果沒有找到,就會去找原型物件的屬性和方法。如果在某一級找到
了,就會停止查詢,並返回結果
1.2,instanceof的原理?
例項物件的proto屬性和建構函式的prototype屬性,判斷是不是同一個引用
在這裡插入圖片描述
1、例項物件的屬性引用的是建構函式的原型物件
2、instanceof用於判斷引用型別屬於哪個建構函式的方法

var M = function(name) {this.name = name};
var o3 = new M('o3');
console.log(o3 instanceof M); // true
console.log(o3 instanceof Object); // true,只要是原型鏈上的建構函式,都會被看成是
object的建構函式,都會返回true
console.log(o3.__proto__===M.prototype); // true
console.log(M.prototype.__proto__===Object.prototype); // true
console.log(o3.__proto__.constructor === M); // true,o3是M這個建構函式直接生成的
console.log(o3.__proto__.constructor === Object); // false
  • new運算子
    new運算子後面跟的是一個建構函式
var new2 = function(func) {
var o = Object.create(func.prototype);
var k = func.call(o); // call轉移上下文
if (type k === 'Object') {
return k;
} else {
return o;
}
}
var o6 = new2(M);
console.log(o6 instanceof M); // true
o6 instanceof Object // true
o6.__proto__.constructor === M; // true
M.prototype.walk = function(){console.log('walk')};
o6.walk(); // 能成功

2、類
2.1,類的宣告?
1、傳統的建構函式,宣告一個類

function Animal() {
this.name = 'name';
}

2、es6中的class宣告

class Animal2{
constructor() {
this.name = name;
}
}

2.2,生成例項?/ 宣告一個類,怎麼生成類的例項?

/*例項化*/
console.log(new Animal(), new Animal2()); // 通過New就可以例項化一個類,如果沒有引數,
Animal後面的()可以不要

3、繼承
繼承的本質是原型鏈
3.1,call、apply的共同點與區別?
1、改變了函式執行上下文
2、call()和apply()主要是能擴充函式賴以執行作用域。兩者的作用方式相同,它們的區別在於接收引數
的方式不同,對於call()而言,第一個引數this與apply()相同,其他的引數必須直接傳給函式,要一個一
個的列出來,而對於apply()來說,apply()可以接收一個數組或arguments物件。所以如何選擇二者,
在於哪種給函式傳引數的方式最簡單。
3.2,用javascript實現物件的繼承/ 繼承的幾種方式,這幾種方式的優缺點?
方法1:藉助建構函式實現繼承(部分繼承)

/**
* 藉助建構函式實現繼承
*/
function Parent1() {
this.name = 'parent';
}
Parent1.prototype.say = function() {}; // 不會被繼承
function Child1() {
// 繼承:子類的建構函式裡執行父級建構函式
// 也可以用apply
// parent的屬性都會掛載到child例項上去
// 藉助建構函式實現繼承的缺點:①如果parent1除了建構函式裡的內容,還有自己原型鏈上的東西,
自己原型鏈上的東西不會被child1繼承
// 任何一個函式都有prototype屬性,但當它是建構函式的時候,才能起到作用(建構函式是有自己的
原型鏈的)
Parent1.call(this);
this.type = 'child1';
}
console.log(new Child1);

(1)如果父類的屬性都在建構函式內,就會被子類繼承。
(2)如果父類的原型物件上有方法,子類不會被繼承。
方法2:藉助原型鏈實現繼承

/**
* 藉助原型鏈實現繼承
*/
function Parent2() {
this.name = 'name';
this.play = [1, 2, 3]
}
function Child2() {
this.type = 'child2';
}
Child2.prototype = new Parent2(); // prototype使這個建構函式的例項能訪問到原型物件上
console.log(new Child2().__proto__);
console.log(new Child2().__proto__ === Child2.prototype); // true
var s1 = new Child2(); // 例項
var s2 = new Child2();
console.log(s1.play, s2.play);
s1.play.push(4);
console.log(s1.__proto__ === s2.__proto__); // true // 父類的原型物件

(1)原型鏈的基本原理:建構函式的例項能訪問到它的原型物件上
(2)缺點:原型鏈中的原型物件,是共用的
方法3:組合方式

/**
* 組合方式
*/
function Parent3() {
this.name = 'name';
this.play = [1, 2, 3];
}
function Child3() {
Parent3.call(this);
this.type = 'child3';
}
Child3.prototype = new Parent3();
var s3 = new Child3();
var s4 = new Child3();
s3.play.push(4);
console.log(s3.play, s4.play);
// 父類的建構函式執行了2次
// 建構函式體會自動執行,子類繼承父類的建構函式體的屬性和方法

①組合方式優化1:

/**
* 組合繼承的優化方式1:父類只執行了一次
*/
function Parent4() {
this.name = 'name';
this.play = [1, 2, 3];
}
function Child4() {
Parent4.call(this);
this.type = 'child4';
}
Child4.prototype = Parent4.prototype; // 繼承父類的原型物件
var s5 = new Child4();
var s6 = new Child4();
console.log(s5 instanceof Child4, s5 instanceof Parent4); // true
console.log(s5.constructor); // Parent4 //prototype裡有個constructor屬性,子類和
父類的原型物件就是同一個物件, s5的constructor就是父類的constructor

②組合方式優化2(最優解決方案):

/**
* 組合繼承優化2
*/
function Parent5() {
this.name = 'name';
this.play = [1, 2, 3];
}
function Child5() {
Parent5.call(this);
this.type = 'child5';
}
Child5.prototype = Object.create(Parent5.prototype); // Object.create建立的物件
就是引數
Child5.prototype.constructor = Child5;
var s7 = new Child5();
console.log(s7 instanceof Child5, s7 instanceof Parent5);
console.log(s7.constructor); // 建構函式指向Child5

優缺點:
原型鏈繼承的缺點
1、字面量重寫原型
一是字面量重寫原型會中斷關係,使用引用型別的原型,並且子型別還無法給超型別傳遞引數。
2、借用建構函式(類式繼承)
借用建構函式雖然解決了剛才兩種問題,但沒有原型,則複用無從談起。所以我們需要原型鏈+借用建構函式的模式,這種模式稱為組合繼承
3、組合式繼承
組合式繼承是比較常用的一種繼承方法,其背後的思路是 使用原型鏈實現對原型屬性和方法的繼承,而通過借用建構函式來實現對例項屬性的繼承。這樣,既通過在原型上定義方法實現了函式複用,又保證每個例項都有它自己的屬性。
4、作用域
1、js沒有塊級作用域,有函式作用域、全域性作用域。es6出現才有塊級作用域。
4.1,說說你對作用域鏈的理解?
作用域鏈的作用是保證執行環境裡有權訪問的變數和函式是有序的,作用域鏈的變數只能向上訪問,變數訪問到window物件即被終止,作用域鏈向下訪問變數是不被允許的。
4.2,this?
1、作為建構函式執行

function Foo(name) {
this.name = name;
}
var f = new Foo('zhangsan');

2、作為物件屬性執行

var obj = {
name: 'A',
printName: function() {
console.log(this.name);
}
}
obj.printName();

3、作為普通函式執行

function fn() {
console.log(this);
}
fn();

4、call apply bind

function fn1(name, age) {
alert(name);
console.log(this);
}
fn1.call({x: 100}, 'zhangsan', 20);
fn1.apply({x:100}, ['zhangsan', 20])
123456
var fn2 = function (name, age) { // 必須是函式表示式,不能是函式宣告,即不能是function
fn2(name, age) {}
alert(name);
console.log(this);
}.bind({y:200});
fn2('zhangsan', 20);

4.3,請說出下列的值?

var items = document.getElementsByTagName('li');
var i,x;
i = 0;
l = items.length;
for (; i < x; i++) {
items[i].addEventListener('click', function() {
console.log(i);
})
}

x
1、i是全域性變數,從0增加到x-1,最後一次x++後成為c成為x。最終點選輸出的就是x。
4.4,請說出下列的值?

!function() {
'use strict';
str = 'A Ha~';
console.log(window.str);
var str = 'Haha~';
console.log(str);
}();

undefined Haha~
1、 console.log(window.str) 改成 cnosole.log(this.str) , 說出this.str打印出來的值
非嚴格模式下:undefined
嚴格模式下:報錯。因為嚴格模式下,this為undefined,所以this.str報錯
5、javaScripti閉包
1、閉包是函式和宣告該函式的詞法環境的組合。
2、使用閉包主要是為了設計私有的方法和變數。閉包的優點是可以避免全域性變數的汙染,缺點是閉包會常駐記憶體,會增大記憶體使用量,使用不當很容易造成記憶體洩露。在js中,函式即閉包,只有函式才會產生作用域的概念
5.1,閉包的特徵?
1、函式巢狀函式
2.、函式內部可以引用外部的引數和變數
3、引數和變數不會被垃圾回收機制回收
5.2,閉包應用場景?
1、作為返回值

function fn() {
var max = 10;
return function bar(x) {
if (x > max) {
console.log(x);
}
}
}
var f1 = fn();
f1(15);

2、作為引數傳遞

var max = 10;
function fn(x) {
if (x > max) {
console.log(x);
}
}
(function(f) {
var max = 100;
f(15);
})(fn);

5.3,實際開發中閉包的應用?
閉包實際應用中主要用於封裝變數,收斂許可權

function isFirstLoad() {
var _list = []; // 有_的變數說明是私有變數,函式內部使用的
return function(id) {
if (_list.indexOf(id) >=0) { // 也可用includes
return false;
} else {
_list.push(id);
return true;
}
}
}
// 使用
var firstLoad = isFirstLoad();
console.log(firstLoad(10)); // true
console.log(firstLoad(10)); // false
console.log(firstLoad(20)); // true
// 你在isFirstLoad函式外面,根本不可能修改掉_list的值

5.4,請說出下列的值?

function num(a) {
'use strict';
var n = 10;
return function (b) {
n +=10;
return (a + b + n);
}
}
var n = num(10);
console.log(n(10));
console.log(n(10));

結果:40 50
1、 40 = 10 + 10 + 20;
2、50 = 10 + 10 + 30;
5.5,請說出下列的值?

function obj() {
this.name = 'Hu';
}
obj.prototype.getName = function() {
return this.name;
}
obj.prototype.delayCall = function() {
window.setTimeout(function() {
console.log(this.getName());
}, 300);
}
var o = new obj();
o.delayCall();

報錯:this.getName() is not a function
1、這個時候的this指向window
5.6,請說出下列的值?

function fun(n, o) {
console.log(o);
return {
fun: function(m) {
return fun(m, n);
}
}
}
var a = fun(0);
a.fun(1);
a.fun(2);
a.fun(3);

結果:
undefined 0 0 0 0
undefined 0 1 2
undefined 0
1
1
6、js執行機制/ 單執行緒/ 非同步
(2)javascript是單執行緒的,主執行緒擁有一個執行棧以及一個任務佇列,主執行緒會依次執行程式碼,當遇
到非同步函式時候,會先將該函式入棧,所有主執行緒函式執行完畢後再將非同步函數出棧,直到所有的非同步
函式執行完畢即可。
(3)Macrotask(巨集任務)和Microtask(微任務)
都屬於上述的非同步任務中的一種,他們分別有如下API:
macrotask: setTimeout, setInterval, setImmediate, I/O, UI rendering
microtasks: process.nextTick, Promise, MutationObserver
(4)promise中的then方法的函式會被推入到microtasks佇列中,而setTimeout函式會被推入到
macrotasks任務佇列中,在每一次事件迴圈中,macrotask只會提取一個執行,而microtask會一直提取,直到microsoft佇列為空為止。
6.1,如何理解js的單執行緒?
只有一個執行緒,同一時間只能做一件事情。
6.2,js為什麼是單執行緒的?
避免dom渲染的衝突
1、瀏覽器需要渲染dom
2、js可以修改dom結構
3、js執行的時候,瀏覽器dom渲染會暫停
4、兩段js也不能同時執行(都修改dom就衝突了)
5、webworder支援多執行緒,但是不能訪問dom
6.3,同步和非同步的區別是什麼?分別舉一個同步和非同步的例子?
1、同步會阻塞程式碼執行,而非同步不會。
2、alert是同步,setTimeout是非同步。
同步:指一個程序在執行某個請求的時候,若該請求需要一段時間才能返回資訊,那麼這個程序將會一
直等待下去,直到收到返回資訊才繼續執行下去;
非同步:指程序不需要一直等下去,而是繼續執行下面的操作,不管其他程序的狀態。當有訊息返回時系統會通知程序進行處理,這樣可以提高執行的效率。

6.4,何時需要非同步?
1、在可能發生等待的情況,等待也是佔線程的一種
2、等待過程中不能像alert一樣阻塞程式進行
3、因此,“等待的情況”都需要非同步
6.5,什麼是任務佇列?
任務佇列(task queue)主要分兩種:
1、巨集任務(macrotask):在新標準中叫task
(1)主要包括:script(整體程式碼),setTimeout,setInterval,setImmediate,I/O,ui rendering
2、微任務(microtask):在新標準中叫jobs
(1)主要包括:process.nextTick, Promise,MutationObserver(html5新特性)
擴充套件:
1、同步任務:在主執行緒上,排隊執行的任務,只有前一個任務執行完畢,才能執行後一個任務;
2、非同步任務:不進入主執行緒,而進入“任務佇列”(task queue)的任務,只有“任務佇列”通知主執行緒,某個非同步任務可以執行了,該任務才會進入主執行緒執行。
6.6,請說出下列值?

setTimeout(() => {
console.log('1')
new Promise((resolve) => {
resolve()
}).then(() => {
console.log('2')
})
}, 0);
setTimeout(() => {
console.log('3')
}, 0);
new Promise((resolve) => {
resolve()
}).then(() => {
console.log('4')
new Promise((resolve) => {
resolve()
}).then(() => {
console.log('5')
})
setTimeout(() => {
console.log('6')
}, 0);
})
new Promise((resolve) => {
resolve()
}).then(() => {
console.log('7')
})

結果:

4751236

6.7,棧和佇列的區別?
1、棧的插入和刪除操作都是在一端進行的,而佇列的操作卻是在兩端進行的。
2、佇列先進先出,棧先進後出。
3、棧只允許在表尾一端進行插入和刪除,而佇列只允許在表尾一端進行插入,在表頭一端進行刪除
6.8,棧和堆的區別?
1、棧區(stack)— 由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。
堆區(heap) — 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由OS回收。
2、堆(資料結構):堆可以被看成是一棵樹,如:堆排序;
棧(資料結構):一種先進後出的資料結構。

  • event loop
    6.9,什麼是event loop?
    事件迴圈。
    1、js實現非同步的具體解決方案:event-loop
    2、執行棧:執行同步任務的
    3、瀏覽器js引擎遇到了setTimeout,識別了這是一個非同步任務,不會將其放入執行棧,而是把它拿
    走,拿走了之後也沒有立馬放到非同步任務佇列中,按延遲時間放入到任務佇列中。同步任務沒有正在執行的東西,就會讀非同步任務,把任務放到執行棧中,執行完了又去讀非同步任務,把任務放到執行棧中,如此迴圈。
    6.10,event-loop流程?
    1、同步程式碼,直接執行
    2、非同步先放在任務佇列中
    3、待同步函式執行完畢,輪詢執行任務佇列的函式
  • 任務佇列
    6.11,哪些語句會放入非同步任務佇列中?
    1、定時任務:setTimeout、setInterval
    2、網路請求:ajax請求、動態 <img 載入
console.log('start');
var img = document.createElement('img');
img.onload = function() {
console.log('loaded');
}
img.src = 'https://ss0.baidu.com/60NW/a.jpg';
console.log('end');
// 打印出來的是start, end, loaded

3、事件繫結:dom事件
4、ES6中的promise.then中的函式
Promise 建構函式是同步執行的,promise.then 中的函式是非同步執行的。
6.12,何時被放入任務佇列?
1、類似onclick等,由瀏覽器核心的DOM binding模組處理,事件觸發時,回撥函式新增到任務佇列
中;
2、setTimeout等,由瀏覽器核心的Timer模組處理,時間到達時,回撥函式新增到任務佇列中;
3、Ajax,由瀏覽器核心的Network模組處理,網路請求返回後,新增到任務佇列中。
ajax載入完成,即ajax什麼時候success,就什麼時候把ajax中的函式放入到非同步佇列中
7、js資料型別
1、值型別/ 基本資料型別:undefined、string、number、boolean
引用型別:物件、陣列、函式
2、複雜資料型別Object包括3種引用型別。
3、基本資料型別儲存在棧中,複雜資料型別儲存在堆中。
4、值型別:不會因為賦值而相互干擾。
5、false: 0、NaN、’’、null、undefined

var obj = {};
if (obj.a == null) {} // 判斷a這個屬性是否存在
function(a, b){if (a == null) {}} // 判斷a這個引數是否存在

7.1、js使用typeof能得到的哪些型別?
typeof只能區分值型別

typeof undefined // undefined
typeof null // object
typeof console.log // function
typeof NaN // number

7.2,如何準確判斷一個變數是陣列型別?

instanceof Array

7.3、js變數按照儲存方式區分為哪些型別,並描述其特點?
1、儲存在棧中:值型別。
2、儲存在堆中:引用型別
引用型別的”資料“儲存在堆中,
引用型別”指向堆中的資料的指標“儲存在棧中。
7.4,null和undefined的區別?
1、null是一個表示”無”的物件,是隻有一個值的特殊型別,轉為數值時為0;
undefined是一個表示”無”的原始值,表示一個空物件引用,轉為數值時為NaN。
2、當宣告的變數還未被初始化時,變數的預設值為undefined。
3、null用來表示尚未存在的物件,常用來表示函式企圖返回一個不存在的物件。
undefined表示”缺少值”,就是此處應該有一個值,但是還沒有定義。
4、null 和 undefined 的值相等,但型別不等
7.5,undefined的典型用法?
1、變數被聲明瞭,但沒有賦值時,就等於undefined。
2、呼叫函式時,應該提供的引數沒有提供,該引數等於undefined。
3、物件沒有賦值的屬性,該屬性的值為undefined。
4、函式沒有返回值時,預設返回undefined。
7.6,null的典型用法?
1、作為函式的引數,表示該函式的引數不是物件。
2、作為物件原型鏈的終點。
7.7**,chrome60+瀏覽器中,a===b的是哪項?**
答案:B

// A
var a = b = 1;
b = 2;
// B
var a = {name: 'jack', age: 27};
var b = a;
b.name = 'may';
// C
var a = [1, 3, 5];
var b = [...a];
// D
var a = [1, 2, 3];
var b = a.push(4); // b = 4;

1、===,絕對等於(值和型別均相等)。
2、C選項:陣列是複合資料結構,b是對a的複製,修改b不會對a產生影響。a、b的型別相同,但是值不同。
8、js中的內建函式/內建物件
8.1,js中有哪些內建函式/ 資料封裝類物件?內建函式:
Number、String、Boolean
Array、Object、Function
Date、RegExp、Error
8.2,js中有哪些內建物件?
內建物件:
Math,Json
8.3,js變數按照儲存方式區分為哪些型別,並描述其特點?
1、值型別和引用型別。
2、值型別儲存的是值 ,賦值之後原變數的值不改變 。
3、 引用型別儲存的是地址 ,賦值之後是把原變數的引用地址賦值給新變數 ,新變數改變原來的會跟
著改變。
8.4,字串方法/ String物件方法?
String物件方法:
concat() includes indexOf() lastIndexOf() slice() toString() valueOf()
charAt() charCodeAt() endsWith fromCahrCode() match() repeat() replace()
search() split startsWith() substr() substring() toLowerCase() toUpperCase()
trim() toLocaleLowerCase `toLocaleUpperCase()
字串屬性:
constructor length prototype
8.5,陣列方法/ Array物件方法?
Array物件方法:

concat() includes indexOf() lastIndexOf() slice() toString() valueOf()
copyWithin() entries() every() fill() filter() find() findIndex() forEach()
from() isArray() join() keys() map() pop() push() reduce() reduceRaight()
reverse() shift() some() sort() splice() ushift()

在這裡插入圖片描述陣列屬性:

constructor length prototype

8.6,陣列API?
1、forEach 遍歷所有元素

var arr = [1, 2, 3];
arr.forEach(function(item, index) {
// 遍歷陣列的所有元素
console.log(index, item);
});

2、every 判斷所有元素是否都符合條件

var arr = [1, 2, 3];
var arr1 = arr.every(function(item, index) {
if (item < 4) {
return true;
}
})
console.log(arr1); // true

3、some 判斷是否有至少一項元素符合條件

var arr = [1, 2, 3];
var result = arr.some(function(item, index) {
if (item < 2) {
return true;
}
})
console.log(result); // true

4、sort 排序

var arr = [1, 5, 2, 7, 3, 4];
var arr2 = arr.sort(function(a, b) {
// 從小到大
return a-b;
// 從大到小
return b-a;
})
console.log(arr2); // 1,2,3,4,5,7

5、map 對元素重新組裝,生成新陣列

var arr = [1, 5, 2, 7, 3, 4];
var arr2 = arr.map(function(item, index) {
return '<b>' + item + '</br>';
})
console.log(arr2);

6、filter 過濾符合條件的元素

var arr = [1, 2, 3, 4];
var arr2 = arr.filter(function(item, index) {
if (item>2) {
return true;
}
})
console.log(arr2); // [3, 4]

8.7,物件API?
1、for in

var obj = {x:100, y:200, z:300};
var key;
for(key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key);
}
}

9,陣列去重
9.1,陣列怎麼去重?(方法)
1、使用陣列方法indexOf來判斷

function sele(arr){
var temp = [];
for( var i = 0 ; i < arr.length ; i++ ){
if( temp.indexOf( arr[ i ] ) == -1 ){
temp.push( arr[ i ] );
}
}
return temp;
}
var arr = ['aa', 'bb', 'cc', '', 1, 0, '1', 1, 'bb', null, undefined, null];
console.log(sele(arr));

2個缺點,一是效率問題,因為加上indexOf相當於是2重迴圈,二是indexOf的相容性問題:IE8–不相容。
2、使用陣列方法indexOf第二種方法 IE8–不相容

function sele( arr ) {
var temp = [];
for( var i = 0 ; i < arr.length ; i++ ){
if( arr.indexOf( arr[ i ] ) == i ){
temp.push( arr[ i ] );
}
}
return temp;
}

比方法(1)效率還要差
3、迴圈

function sele( arr ) {
var temp = [];
for( var i = 0 ; i < arr.length ; i++ ){
for( var j = i + 1 ; j < arr.length ; j++ ){
if( arr[ i ] === arr[ j ] ){
j = ++i;
}
}
temp.push( arr[ i ] );
}
return temp;
}
function unique3(array)
{
var result = [];
var hash = {};
for(var i=0; i<array.length; i++)
{
var key = (typeof array[i]) + array[i];
if(!hash[key])
{
result.push(array[i]);
hash[key] = true;
以上方法中之所以給key添加了型別字首,是因為要區分’1’和15、使用es6中includes方法
6、es6的set
9.2,對上述陣列去重方法速度比較?(效能)
console.time, console.timeEnd
9.3,一句話陣列去重?
}
}
return result;
}
var arr = ['aa', 'bb', 'cc', '', 1, 0, '1', 1, 'bb', null, undefined, null];
console.log(unique3(arr));

以上方法中之所以給key添加了型別字首,是因為要區分’1’和1。
5、使用es6中includes方法

function sele( arr ) {
var temp = [];
arr.forEach( ( v ) => {
temp.includes( v ) || temp.push( v );
} )
return temp;
}

6、es6的set

function unique(array){return Array.from(new Set(array));}
// 或者寫成(建議寫法)
const unique = arr => [...new Set(arr)]
// 也可以是
const unique = arr => {return [...new Set(arr)]}
var arr = ['aa', , '', 1, 0, '1', 1, , null, undefined, null];
console.log(unique(arr));

9.2,對上述陣列去重方法速度比較?(效能)

console.time, console.timeEnd
var testArray = [];
for(var i=0; i<500000; i++)
{
testArray.push(parseInt(Math.random()*100));
}
function test(fn, name)
{
console.time(name);
fn(testArray);
console.timeEnd(name);
}
test(unique1, '第1種實現');
test(unique2, '第2種實現');
test(unique3, '第3種實現');
test(unique4, '第4種實現');

9.3,一句話陣列去重?
new Set():Set本身是一個建構函式,用來生成Set資料結構

const unique = arr => [...new Set(arr)]
var arr = ['aa', , '', 1, 0, '1', 1, , null, undefined, null];
console.log(unique(arr));

9.4,保留陣列中非重複元素?
indexOf 是查某個指定的字串在字串首次出現的位置(索引值從左往右0、1、2…) (也就是從前往後查)
lastIndexOf 是從右向左查某個指定的字串在字串中最後一次出現的位置(索引值從左往右0、1、2…)(也就是從後往前查)

let arr = [11, 23, 26, 23, 11, 9]
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) ===
arr.lastIndexOf(i))
console.log(filterNonUnique(arr)); // [ 26, 9 ]

9.5,保留陣列中重複元素?

let arr = [11, 23, 26, 23, 11, 9]
const filterUnique = arr => arr.filter(i => arr.indexOf(i) !==
arr.lastIndexOf(i))
console.log(filterUnique(arr)); // [ 11, 23, 23, 11 ]

10、js邏輯判斷
一、 || 判斷
1、只要‘||’前面為false,無論’||‘後面是true還是false, 結果都返回’||‘後面的值。
2、只要’||‘前面是true,無論’||‘後面是true還是false,結果都返回’||‘前面的值。
二、&& 判斷
1、只要‘&&’前面是false,無論’&&‘後面是true還是false,結果都返回’&&‘前面的值。
2、只要’&&‘前面是true,無論’&&‘後面是true還是false,結果都返回’&&‘後面的值。
三、優先順序順序中,邏輯’&&‘的優先順序高於邏輯’||’。