此文主旨是記錄面試中遇到的面試題,包括js中常見,易錯,重要知識點
window.onload是在頁面中包含圖片在內的全部元素所有加載完成再執行; $(document).ready()是DOM樹加載完成以後執行,不包含圖片,其餘媒體文件; 所以$(document).ready()快於window.onload執行;
const arr = ['a','bb','22','a','yuci','haha','22'];
1.es6數據結構Setjavascript
let unique = new Set(arr); console.log(Array.from(unique));
2.使用push()html
let arr2 = []; for(let i = 0; i < arr.length; i++) { if(arr2.indexOf(arr[i]) == -1) { //不包含某個值則返回-1 arr2.push(arr[i]); } } console.log(arr2);
//若是當前數組的第i項在當前數組中第一次出現的位置不是i,那麼表示第i項是重複的,忽略掉。不然存入結果數組 let arr3 = [arr[0]]; for(let i = 1; i < arr.length; i++) { if(arr.indexOf(arr[i]) == i) { arr3.push(arr[i]); } } console.log(arr3);
3.排序去除相鄰重複元素java
let arrSort = arr.sort(); let arr4 = []; for(let i = 0; i< arrSort.length; i++) { if(arrSort[i] != arrSort[i+1]) { arr4.push(arrSort[i]); } } console.log(arr4);
4.使用splice()node
let len = arr.length; for(let i = 0; i < len; i++) { for(let j = i + 1; j < len; j++) { if(arr[i] === arr[j]) { arr.splice(i,1); len--; j--; } } } console.log(arr);
得益於事件冒泡,當多個元素有相同的事件,將事件綁定在父元素git
var oUl = document.getElementById('oul'); oUl.addEventListener('click', function(e) { var e = e||window.event; var tar = e.target; if(tar.nodeName === 'LI') { alert(tar.innerHTML); } })
更詳細請看:事件委託es6
更詳細請看:判斷數據類型github
同步:因爲js單線程,同步任務都在主線程上排隊執行,前面任務沒執行完成,後面的任務會一直等待; 異步:不進入主線程,進入任務隊列,等待主線程任務執行完成,開始執行。最基礎的異步操做setTimeout和setInterval,等待主線程任務執行完,在開始執行裏面的函數;
更詳細請看:js運行機制面試
false,null,0,「」,undefined,NaN數組
存儲地: 簡單數據類型:存儲在棧中; 引用數據類型:存儲在堆中,在棧中存儲了指針,指向存儲在堆中的地址,解釋器會先檢索在棧中的地址,從堆中得到實體; 大小: 簡單數據類型:大小固定,佔用空間小,頻繁使用,因此存儲在棧中; 引用數據類型:大小不固定,佔用空間大;
何爲閉包:有權訪問另外一個做用域中變量的函數 閉包特性:可實現函數外訪問函數內變量,外層變量能夠不被垃圾回收機制回收 爲何?怎麼解決?
for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 1000); }
輸出結果都爲10,由於for()循環過程當中每次傳值,匿名函數並無執行,至關於執行10次function(){console.log(i);},循環結束i變爲10,因此輸出所有爲10;瀏覽器
使用閉包,自執行匿名函數包裹:
for(var i = 0; i < 10; i++) { (function(j) { setTimeout(function() { console.log(j); }, 1000); })(i); }
外部匿名函數當即執行,把 i 做爲參數,賦值給 j ,由於是當即執行,因此每次循環輸出不一樣值。
引用外層變量不被回收,會相比其餘函數佔用更高內存,使用不當容易形成內存泄漏。
全局範圍:指向window(嚴格模式下不存在全局變量,指向undefined); 普通函數調用:指向window; 對象方法調用:指向最後調用它的對象; 構造函數調用:指向new出來的對象; 顯示設置this:call,apply方法顯示將this指向第一個參數指明的對象
建立一個新對象foo; 並將它的__proto__指向其構造函數的prototype,foo.__proto__ = Foo.prototype; 動態將this指向新對象,Foo.apply(foo,arguments); 執行函數體中的代碼; 放回新對象foo;
建立一個函數就會爲其建立一個prototype屬性,指向這個函數的原型對象,原型對象會自動得到constructor屬性,指向prototype屬性所在函數。
Function.prototype.a = "a"; Object.prototype.b = "b"; function Person(){} console.log(Person); //function Person() let p = new Person(); console.log(p); //Person {} 對象 console.log(p.a); //undefined console.log(p.b); //b
p.__proto__ === Person.prototype;Person.prototype.constructor === Person
當調用某種方法或查找某種屬性時,首先會在自身調用和查找,若是自身並無該屬性或方法,則會去它的__proto__屬性中調用查找,也就是它構造函數的prototype中調用查找,若是構造函數中也沒有該屬性方法,則會去構造函數的隱式原型中查找,一直到null,就這樣造成原型鏈。
更多有關原型請看:原型和原型鏈
原型鏈繼承:
Child()的原型做爲Parent()的實例來繼承Parent()的方法屬性
由於全部實例都繼承原型方法屬性,其中一個實例對原型屬性值更改後,全部實例調用該屬性的值所有更改
function Parent() {} Parent.prototype.parentSay = function() { return 'i am parent'; } function Child() {} Child.prototype.childSay = function() { return 'i am child'; } Child.prototype = new Parent(); var par = new Parent(); var kid = new Child(); console.log(kid.parentSay()); //i am parent
構造函數繼承:
在子類的構造函數內部經過call或apply來調用父類構造函數
沒法實現函數的複用
function People() { this.name = ['zhangsan','lisi','wangwu']; } function Person() { People.call(this); } var per1 = new Person(); per1.name.push('zhanliu'); console.log(per1.name); //["zhangsan", "lisi", "wangwu", "zhanliu"] var per2 = new Person(); console.log(per2.name); //["zhangsan", "lisi", "wangwu"]
組合繼承:
將原型鏈繼承和構造函數繼承結合,最經常使用的繼承模式
原型鏈繼承共享的屬性和方法,構造函數繼承實例屬性
function People(num) { this.num = num; this.name = ['zhangsan','lisi','wangwu']; } People.prototype.numCount = function() { console.log(this.num); } function Person(num) { People.call(this, num); } //繼承方式 Person.prototype = new People(); Person.prototype.constructor = Person; var per1 = new Person(10); per1.name.push('zhaoliu'); console.log(per1.name); //["zhangsan", "lisi", "wangwu", "zhanliu"] per1.numCount(); //10 var per2 = new Person(20); console.log(per2.name); //["zhangsan", "lisi", "wangwu"] per2.numCount(); //20
更多繼承方式請看:繼承方式
改變原數組:
尾部刪除pop(),尾部添加push(),頭部刪除shift(),頭部添加unshift(),排序sort(),顛倒數組元素reverse(),刪除或插入元素splice();
不會改變元素組:
合併數組concat(),拼接數組元素join(),截取元素slice(),indexOf(),lastIndexOf(),toString()
更詳細數組方法總結請看:Array數組方法總結
Cookie:用於客戶端與服務端通訊,也具備本地存儲的功能 localStorage,sessionStorage:專門用於存儲 區別: 大小:Cookie容量爲4K,由於用於客戶端與服務端通訊,全部http都攜帶,若是太大會下降效率; localStorage,sessionStorage大小爲5M。 失效時間:Cookie會在瀏覽器關閉時刪除,除非主動設置刪除時間;localStorage一直都在直到用戶主動刪除或清除瀏覽器緩存;sessionStorage在瀏覽器關閉時刪除。
若有錯誤,歡迎指正