前端JS初級面試題二 (。•ˇ‸ˇ•。)老鐵們!快來瞧瞧自己都會了麼
目錄
- 傳統事件繫結和符合W3C標準的事件繫結有什麼區別?
- IE 和標準下有哪些相容性的寫法
- JavaScript 如何實現繼承?
- JavaScript 建立物件的幾種方式?
- this指標,閉包,作用域
- 如何阻止事件冒泡和預設事件
- JavaScript 的同源策略
- JavaScript是一門什麼樣的語言,它有哪些特點?
- 如何檢測陣列的資料型別?
- 新增 刪除 替換 插入到某個節點的方法
- javascript的本地物件,內建物件和宿主物件
- 已知ID的Input輸入框,希望獲取這個輸入框的輸入值,怎麼做?(不使用第三方框架)
- 希望獲取到頁面中所有的checkbox怎麼做?(不使用第三方框架)
- 設定一個已知ID的DIV的html內容為xxxx,字型顏色設定為黑色(不使用第三方框架)
- 當一個DOM節點被點選時候,我們希望能夠執行一個函式,應該怎麼做?
- Javascript的事件流模型都有什麼?
- 列舉瀏覽器物件模型BOM裡常用的至少4個物件,並列舉window物件的常用方法至少5個
- 簡述建立函式的幾種方式
- iframe的優缺點?
- 請你談談Cookie的弊端?
- js延遲載入的方式有哪些?
- documen.write和 innerHTML 的區別?
- 哪些操作會造成記憶體洩漏?
- 解釋jsonp的原理,以及為什麼不是真正的ajax
- javascript 中的垃圾回收機制?
- BOM物件有哪些,列舉window物件?
- 簡述readyonly與disabled的區別?
- 為什麼擴充套件javascript內建物件不是好的做法?
1. 傳統事件繫結和符合W3C標準的事件繫結有什麼區別?
傳統事件繫結
<div onclick="">123</div>
div1.onclick = function(){};
<button onmouseover=""></button>
注意:
如果給同一個元素繫結了兩次或多次相同型別的事件,那麼後面的繫結會覆蓋前面的繫結
(不支援DOM事件流 :事件捕獲階段=>目標元素階段=>事件冒泡階段)
符合W3C標準的事件繫結的方式 addEventListener/attachEvent
-
非IE瀏覽器:
addEventListener / removeEventListener
所有的DOM節點都包含這兩個方法,並且他們都接受三個引數:
1.事件型別
2.事件處理方法
3.布林引數,預設false
(true捕獲階段呼叫事件處理方法;false冒泡階段呼叫事件處理方法。)//addEventListener let box = document.querySelector('.box') box.addEventListener('click',function(){ console.log('box clicked...') }) function xxx(){console.log('box clicked...')} box.addEventListener('click',xxx) //新增事件 box.removeEventListener('click',xxx) //刪除事件
注意:
如果給同一個元素繫結了兩次或多次相同型別的事件,繫結依次觸發
支援DOM事件流
進行事件繫結不需要on
字首 -
IE瀏覽器:
attachEvent / detachEvent
這兩個方法都接受兩個相同的引數。
1.事件處理程式名稱
2.事件處理程式方法IE只支援事件冒泡 let box = document.querySelector('.box') function xxx(){console.log('box clicked...')} box.attachEvent('onclick',xxx) // 新增事件 box.detachEvent('onclick',xxx) // 刪除事件
注意:
進行事件型別傳參需要帶上on
字首
這種方式只支援事件冒泡,不支援事件捕獲
相容性:
attachEvent
——相容:IE7、IE8;不相容firefox、chrome、IE9、IE10、IE11、safari、opera
addEventListener
——相容:firefox、chrome、IE、safari、opera;不相容IE7、IE8
2. IE 和標準下有哪些相容性的寫法
ev = event || window.event
獲取觸發事件的物件
var target = ev.srcElement || ev.target
獲取事件的源物件
document.documentElement.clientWidth/Height || document.body.clientWidth/Height
獲取瀏覽器視窗尺寸
3. JavaScript 如何實現繼承?
?(1) 原型鏈繼承
function Animals() {
this.age = 1;
}
Animals.prototype.getAge = function(){
return this.age;
};
function Cat() {
this.name = '咪咪'
}
// 繼承,用 Animals 型別的一個例項來重寫 Cat 型別的原型物件
// 這一步,讓Cat的物件擁有了Animals物件的屬性,方法
Cat.prototype = new Animals();
var cat = new Cat();
console.log(cat.name) // '咪咪'
console.log(cat.age) // 1
console.log(cat.getAge()) // 1
特點:
- 非常純粹的繼承關係,例項是子類的例項,也是父類的例項
- 父類新增原型方法/原型屬性,子類都能訪問到
- 簡單,易於實現
缺點:
- 要想為子類新增屬性和方法,必須要在new Cat()這樣的語句之後執行,不能放到構造器中
- 無法實現多繼承
- 來自原型物件的引用屬性被所有例項共享
- 建立子類例項時,無法向父類建構函式傳參
?(2) 借用建構函式繼承(也稱偽造物件或經典繼承)
在子型別建構函式的內部呼叫超型別建構函式;使用 apply()
或 call()
方法將父物件的建構函式繫結在子物件上
function Animals() {
// 定義引用型別值屬性
this.colors = ["red","green","blue"];
}
function Cat() {
// 繼承 Animals,在這裡還可以給超型別建構函式傳參
Animals.call(this);
}
var cat1 = new Cat();
cat1.colors.push('yellow');
console.log(cat1.colors); // ["red", "green", "blue", "yellow"]
var cat2 = new Cat();
console.log(cat2.colors); // ["red", "green", "blue"]
通過使用 apply() 或 call() 方法,我們實際上是在將要建立的 Cat 例項的環境下呼叫了 Animals 建構函式。這樣一來,就會在新 Cat 物件上執行 Animals() 函式中定義的所有物件初始化程式碼。結果 Cat 的每個例項就都會具有自己的 colors 屬性的副本了
特點:
- 解決了原型鏈繼承中,子類例項共享父類引用屬性的問題
- 建立子類例項時,可以向父類傳遞引數
- 可以實現多繼承(call多個父類物件)
缺點:
- 例項並不是父類的例項,只是子類的例項
- 只能繼承父類的例項屬性和方法,不能繼承原型屬性/方法
- 無法實現函式複用,每個子類都有父類例項函式的副本,影響效能
?(3)原型+建構函式組合繼承 (也稱偽經典繼承)
將原型鏈和借用建構函式的技術組合到一塊。使用原型鏈實現對原型屬性和方法的繼承,而通過借用建構函式來實現對例項屬性的繼承。這樣,既通過在原型上定義方法實現了函式複用,又能夠保證每個例項都有自己的屬性。
function Animals(age) {
this.age = age;
this.colors = ["red","green","blue"];
}
Animals.prototype.getAge = function(){
return this.age;
};
function Cat(age, name) {
// 借用建構函式方式繼承屬性
Animals.call(this,age);
this.name = name;
}
// 原型鏈方式繼承方法
Cat.prototype = new Animals();
Cat.prototype.constructor = Cat;
Cat.prototype.getName = function(){
return this.name;
};
var cat1 = new Cat(1,"咪咪");
cat1.colors.push("yellow");
console.log(cat1.colors); // ["red", "green", "blue", "yellow"]
console.log(cat1.getAge()); // 1
console.log(cat1.getName()); // 咪咪
var cat2 = new Cat(2, "小白")
console.log(cat2.colors); // ["red", "green", "blue"]
console.log(cat2.getAge()); // 2
console.log(cat2.getName()); // 小白
特點:
- 組合繼承避免了原型鏈和借用建構函式的缺陷,融合了它們的優點(可以繼承例項屬性/方法,也可以繼承原型屬性/方法),成為 javascript 中最常用的繼承模式。
- 既是子類的例項,也是父類的例項
- 不存在引用屬性共享問題
- 可傳參
- 函式可複用
- 使用
instanceof
操作符和isPrototype()
方法也能夠用於識別基於組合繼承建立的物件。
缺點:
- 無論在什麼情況下,都會呼叫兩次超型別建構函式:一次是在建立子型別原型的時候,另一次是在子型別建構函式內部。
?(4)原型式繼承
使用 Object.create() 方法實現原型式繼承
這個方法接收兩個引數:一是用作新物件原型的物件和一個為新物件定義額外屬性的物件。在傳入一個引數的情況下,此方法與 object() 方法作用一致。 在傳入第二個引數的情況下,指定的任何屬性都會覆蓋原型物件上的同名屬性。
var person = {
name: "luochen",
colors: ["red","green","blue"]
};
var anotherPerson1 = Object.create(person,{
name: {
value: "tom"
}
});
var anotherPerson2 = Object.create(person,{
name: {
value: "jerry"
}
});
anotherPerson1.colors.push("purple");
alert(anotherPerson1.name); // "tom"
alert(anotherPerson2.name); // "jerry"
alert(anotherPerson1.colors); // "red,green,blue,purple"
alert(anotherPerson2.colors); // "red,green,bule,purple";
只是想讓一個物件與另一個物件類似的情況下,原型式繼承是完全可以勝任的。
缺點: 包含引用型別值的屬性始終都會共享相應的值
?(5)寄生式繼承
// 建立一個僅用於封裝繼承過程的函式,該函式在內部以某種方式來增強物件,最後返回這個物件
function createPerson(original){
// 通過 Object.create() 函式建立一個新物件
var clone = Object.create(original);
// 增強這個物件
clone.sayGood = function(){
alert("hello world!!!");
};
// 返回這個物件
return clone;
}
在主要考慮物件而不是自定義型別和建構函式的情況下,寄生式繼承也是一種有用的模式。
缺點:
- 做不到函式複用,都是每次建立物件都會建立一遍方法,記憶體佔用大
?(6) 寄生組合式繼承
通過借用建構函式來繼承屬性,通過原型鏈的混成形式來繼承方法。本質上,就是使用寄生式繼承來繼承超型別的原型,然後再將結果指定給子型別的原型
function Animals(age) {
this.age = age;
this.colors = ["red","green","blue"];
}
Animals.prototype.getAge = function(){
return this.age;
};
function Cat(age, name) {
// 借用建構函式方式繼承屬性
Animals.call(this,age);
this.name = name;
}
// 建立超型別原型的一個副本
var animalsCopy = Object.create(Animals.prototype);
// 重設因重寫原型而失去的預設的 constructor 屬性
animalsCopy.constructor = Cat;
// 將新建立的物件賦值給子型別的原型
Cat.prototype = animalsCopy;
Cat.prototype.getName = function() {
return this.name;
}
var cat1 = new Cat(1,"咪咪");
cat1.colors.push("yellow");
console.log(cat1.colors); // ["red", "green", "blue", "yellow"]
console.log(cat1.getAge()); // 1
console.log(cat1.getName()); // 咪咪
var cat2 = new Cat(2, "小白")
console.log(cat2.colors); // ["red", "green", "blue"]
console.log(cat2.getAge()); // 2
console.log(cat2.getName()); // 小白
這個例子的高效率體現在它只呼叫一次 Animals
建構函式,並且因此避免了在 Cat.prototype
上面建立不必要,多餘的屬性。與此同時,原型鏈還能保持不變;因此還能夠正常使用 instance 操作符
和 isPrototype() 方法
缺點:程式碼比較複雜
4. JavaScript 建立物件的幾種方式?
?(1) 使用物件字面量建立
var Person = {
name:'小白',
age:23,
say: function() {
console.log('我是:' + this.name);
}
}
Person.say(); // 我是:小白
?(2) 使用Object 建構函式建立
var Person = new Object();
Person.name = '小白';
Person.age = 23;
Person.say = function() {
console.log('我是:' + this.name);
}
Person.say(); // 我是:小白
推薦使用物件字面量{}
形式建立,效率比較高
?(3) 使用工廠模式建立物件
function createPerson(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.say = function() {
console.log('say' )
}
return o;
}
var person1 = createPerson('name',29)
person1.say();
建立createPerson的時候,返回的是一個物件,那麼我們就無法判斷返回的物件究竟是一個什麼樣的型別。於是出現了使用建構函式建立物件。
?(4) 使用建構函式建立物件
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.say = function() {
console.log(this.name + ':' + this.age + '歲');
};
var person1 = new Person('小白', '12');
person1.say(); // 小白:12歲
var person2 = new Person('小花', '11');
person2.say(); // 小花:11歲
這種方式與工廠模式相比:
- 沒有顯示地構建物件
- 直接將屬性和方法賦給了this物件
- 沒有
return
語句 - 可以通過
instanceof
識別物件的型別
使用內建物件建立物件
如:var str = new String("例項初始化String");
var str1 = "直接賦值的String";
var func = new Function("x","alert(x)");
// 示例初始化func
var obj = new Object();
// 示例初始化一個Object
5. this指標,閉包,作用域
this: 指向呼叫上下文
閉包: 內層作用域可以訪問外層作用域的變數
作用域: 定義一個函式就開闢了一個區域性作用域,整個JS執行環境有一個全域性作用域
6. 如何阻止事件冒泡和預設事件
防止冒泡和捕獲
w3c的方法是e.stopPropagation()
,IE則是使用e.cancelBubble = true
取消預設事件
w3c的方法是e.preventDefault()
,IE則是使用e.returnValue = false
7. JavaScript 的同源策略
同源策略
- ajax 請求時,瀏覽器要求當前網頁和server必須同源(安全)
- 同源:協議,域名,埠,三者必須一致
詳情請點選檢視另一篇部落格 同源策略和跨域 (ノ°▽°)ノ 衝鴨!征服她!!!
8. JavaScript是一門什麼樣的語言,它有哪些特點?
js就是物件導向的弱型別語言
語言特性:物件導向(要掌握建立物件的多種方式,繼承的多種方式、原型鏈),動態/弱型別語言
動態語言的特性
var num=10;//num是一個數字型別
num="jim";//此時num又變成一個字串型別
//我們把一個變數用來儲存不同資料型別的語言稱之為一個動態語言,或者說是一個弱型別語言
9. 如何檢測陣列的資料型別?
檢測陣列的幾種方式:
Array.isArray([1,2,3]); // true (ES5)
toString.call([]); // "[object Array]"
var arr = [];
arr.constructor; // ƒ Array() { [native code] } 不推薦使用,因為constructor是可以修改的。
[] instanceof Array // true
10. 新增 刪除 替換 插入到某個節點的方法
原生:
appendChild()
// 新增
removeChild()
// 刪除節點
replaceChild(新節點,舊節點)
// 替換(前替換後)
insertBefore(插入節點,被插節點)
// 插入(前插後)
jq:
// 新增
append()
(舊節點新增新節點後面)
appendTo()
(新節點新增到舊節點後面)
prepend()
(舊節點新增新節點的前面)
prependTo()
(新節點新增到舊節點的前面)
remove()
// 刪除
empty()
// 清空
// 插入
after()
// 舊節點後面插入 新節點
before()
// 舊節點前面插入 新節點
insertAfter()
// 新節點插到舊節點後
insertBefore()
// 新節點插到舊節點前
replaceWith()
// 替換
11. javascript的本地物件,內建物件和宿主物件
本地物件為array
obj
regexp
等可以new例項化
內建物件為gload
Math
等不可以例項化的
宿主物件為瀏覽器自帶的document
, window
等
12. 已知ID的Input輸入框,希望獲取這個輸入框的輸入值,怎麼做?(不使用第三方框架)
document.getElementById(“ID”).value
13. 希望獲取到頁面中所有的checkbox怎麼做?(不使用第三方框架)
var domList = document.getElementsByTagName(‘input’)
var checkBoxList = [];
var len = domList.length; //快取到區域性變數
while (len--) { //使用while的效率會比for迴圈更高
if (domList[len].type == ‘checkbox’) {
checkBoxList.push(domList[len]);
}
}
14. 設定一個已知ID的DIV的html內容為xxxx,字型顏色設定為黑色(不使用第三方框架)
var dom = document.getElementById(“ID”);
dom.innerHTML = “xxxx”
dom.style.color = “#000”
15. 當一個DOM節點被點選時候,我們希望能夠執行一個函式,應該怎麼做?
直接在DOM裡繫結事件: <div onclick=”test()”></div>
在JS裡通過onclick繫結: xxx.onclick = test
通過事件新增進行繫結: addEventListener(xxx, ‘click’, test)
16. Javascript的事件流模型都有什麼?
事件冒泡: 事件開始由最具體的元素接受,然後逐級向上傳播
事件捕捉: 事件由最不具體的節點先接收,然後逐級向下,一直到最具體的
DOM事件流: 三個階段:事件捕捉,目標階段,事件冒泡
17. 列舉瀏覽器物件模型BOM裡常用的至少4個物件,並列舉window物件的常用方法至少5個
物件:window, document, location, screen, history, navigator
方法: alert(), confirm(), prompt(), open(), close()
18. 簡述建立函式的幾種方式
第一種(函式宣告):
function sum1(num1,num2){
return num1+num2;
}
第二種(函式表示式)
var sum2 = function(num1,num2){
return num1+num2;
}
第三種(函式物件方式):
var sum3 = new Function("num1","num2","return num1+num2");
19. iframe的優缺點?
優點:
- 解決載入緩慢的第三方內容如圖示和廣告等的載入問題
- Security sandbox
- 並行載入指令碼
缺點:
- iframe會阻塞主頁面的Onload事件
- 即時內容為空,載入也需要時間
- 沒有語意
20. 請你談談Cookie的弊端?
缺點:
- Cookie數量和長度的限制。每個domain最多隻能有20條cookie,每個cookie長度不能超過4KB,否則會被截掉。
- 安全性問題。如果cookie被人攔截了,那人就可以取得所有的session資訊。即使加密也與事無補,因為攔截者並不需要知道cookie的意義,他只要原樣轉發cookie就可以達到目的了。
- 有些狀態不可能儲存在客戶端。例如,為了防止重複提交表單,我們需要在伺服器端儲存一個計數器。如果我們把這個計數器儲存在客戶端,那麼它起不到任何作用。
更多詳情,請點選我的這篇部落格檢視:٩(๑❛ᴗ❛๑)۶
cookie localStorage sessionStorage (¦3」∠) 看完你居然就懂了!!!
21. js延遲載入的方式有哪些?
- defer和async
- 動態建立DOM方式(建立script,插入到DOM中,載入完畢後callBack)
- 按需非同步載入js
22. documen.write和 innerHTML 的區別?
document.write
只能重繪整個頁面innerHTML
可以重繪頁面的一部分
23. 哪些操作會造成記憶體洩漏?
記憶體洩漏指任何物件在您不再擁有或需要它之後仍然存在。
垃圾回收器定期掃描物件,並計算引用了每個物件的其他物件的數量。如果一個物件的引用數量為 0(沒有其他物件引用過該物件),或對該物件的惟一引用是迴圈的,那麼該物件的記憶體即可回收。
造成記憶體洩露的操作有:
setTimeout
的第一個引數使用字串而非函式的話,會引發記憶體洩漏。- 閉包
- 控制檯日誌
- 迴圈(在兩個物件彼此引用且彼此保留時,就會產生一個迴圈)
24. 解釋jsonp的原理,以及為什麼不是真正的ajax
JSONP:
動態建立script標籤,回撥函式
jsonp可以用來解決跨域問題,詳情請點選檢視:同源策略和跨域 (ノ°▽°)ノ 衝鴨!征服她!!!
Ajax:
Ajax是頁面無重新整理請求資料操作
Ajax, jQuery ajax, fetch,axios ヾ(⌐■_■)ノ看完 你就明白了~~
25. javascript 中的垃圾回收機制?
- 在Javascript中,如果一個物件不再被引用,那麼這個物件就會被GC回收。
- 如果兩個物件互相引用,而不再 被第3者所引用,那麼這兩個互相引用的物件也會被回收。
- 因為函式a被b引用,b又被a外的c引用,這就是為什麼 函式a執行後不會被回收的原因。
26. BOM物件有哪些,列舉window物件?
window物件
,是JS的最頂層物件,其他的BOM物件都是window物件的屬性;document物件
,文件物件;location物件
,瀏覽器當前URL資訊;navigator物件
,瀏覽器本身資訊;screen物件
,客戶端螢幕資訊;history物件
,瀏覽器訪問歷史資訊;
27. 簡述readyonly與disabled的區別
ReadOnly
和Disabled
的作用是使使用者不能夠更改表單域中的內容.
區別:
Readonly
只針對input(text/password)
和textarea
有效,而disabled
對於所有的表單元素有效,包括select,radio,checkbox,button
等。- 在表單元素使用了
disabled
後,我們將表單以POST
或者GET
的方式提交的話,這個元素的值不會被傳遞出去,而readonly
會將該值傳遞出去
28. 為什麼擴充套件javascript內建物件不是好的做法?
因為你不知道哪一天瀏覽器或javascript
本身就會實現這個方法,而且和你擴充套件的實現有不一致的表現。到時候你的javascript
程式碼可能已經在無數個頁面中執行了數年,而瀏覽器的實現導致所有使用擴充套件原型的程式碼都崩潰了。。。
相關文章
- java初級面試題(二)Java面試題
- ?來瞧瞧阿里一面都面些什麼(二)| 掘金技術徵文阿里
- 這是今年前端最常見的面試題,你都會了嗎?前端面試題
- 都9012年了,怎麼還會有人不會面試?面試
- 面試現場:這些常問的面試題你都會了嗎面試題
- 前端js面試題前端JS面試題
- ?來瞧瞧阿里一面都面些什麼(筆試+機試)阿里筆試
- 世界頂級公司的前端面試都問些什麼前端面試
- 前端面試總結篇(初級)前端面試
- 初級前端開發面試總結前端面試
- 前端面試之js相關問題(二)前端面試JS
- 3道常見的vue面試題,你都會了嗎?Vue面試題
- 【面試篇】金九銀十面試季,這些面試題你都會了嗎?面試題
- Web前端求職時都會被問到的Redis面試題分享!Web前端求職Redis面試題
- Node.js 給前端帶來了什麼Node.js前端
- 寫給初級前端的面試經驗前端面試
- JS每日一題: 前端的快取有哪些?都適用什麼場景?區別是什麼?JS每日一題前端快取
- 前端面試之new操作符具體都幹了什麼?前端面試
- 美團二面:為什麼不推薦使用 MyBatis 二級快取?大部分人都答不上來!MyBatis快取
- Java 14 都快來了,為什麼還有這麼多人固守Java 8?Java
- 金三銀四跳槽季,這些面試題你都會了嗎?面試題
- 你們的軟體工程師面試都弱爆了軟體工程工程師面試
- 兄弟們,大廠機會來了
- 百度Android面試真題解析:二次面試終拿到offer,這些面試重點我都整理出來了!Android面試
- 前端Node.js面試題前端Node.js面試題
- 那些拼命加班的程式設計師們,後來都怎麼樣了?程式設計師
- 餓了麼快應用初體驗
- 面試官:你都工作3年了,這個演算法題都不會?面試演算法
- 2020年兩會:關於“遊戲”代表們都說了什麼?遊戲
- 你們要的面試題來啦!面試題
- 大部分人都會做錯的經典JS閉包面試題JS面試題
- 前端高階面試題@JS篇前端面試題JS
- 前端常見面試題(js部分)前端面試題JS
- 前端JS面試題簡約版前端JS面試題
- 前端工程師面試題(js)前端工程師面試題JS
- 前端基礎面試題@JS篇前端面試題JS
- 高階前端開發者必會的34道Vue面試題系列(二)前端Vue面試題
- 2019初級中級高階web前端面試題超全面細節解析Web前端面試題