前兩天總結了一下HTML+CSS方面的面試題 (傳送門),今天翻看了一些 JavaScript
面試中常見的幾個問題(只是一部分,會持續更新),分享給有須要的小夥伴,歡迎star
關注html
若是文章中有出現紕漏、錯誤之處,還請看到的小夥伴留言指正,先行謝過git
如下 ↓github
6種原始數據類型:web
true
和 false
Null
類型只有一個值: null
,特指對象的值未設置undefined
Symbols
)是ECMAScript第6版新定義的。符號類型是惟一的而且是不可修改的引用類型:Object
面試
詳見 JavaScript中的數據類型segmentfault
typeof
操做符:返回一個字符串,表示未經計算的操做數的類型typeof
操做符對於簡單數據類型,返回其自己的數據類型,函數對象返回function
,其餘對象均返回Object
null
返回Object
數組
A instanceof B
,返回一個Boolean
類型的值
instanceof
檢測的是原型,只能用來判斷兩個對象是否屬於實例關係, 而不能判斷一個對象實例具體屬於哪一種類型
let a = []; a instanceof Array // true a instanceof Object // true
變量a 的__proto__
直接指向Array.prototype
,間接指向Object.prototype
,因此按照instanceof
的判斷規則,a 就是Object
的實例.針對數組的這個問題,ES5 提供了Array.isArray()
方法 。該方法用以確認某個對象自己是否爲 Array 類型
prototype
原型,而後再在 prototype
上添加一個 constructor
屬性,並讓其指向該函數的引用null
和undefined
是無效的對象,所以是不會有constructor
存在的,這兩種類型的數據須要經過其餘方式來判斷函數的
constructor
是不穩定的,這個主要體如今自定義對象上,當開發者重寫prototype
後,原有的constructor
引用會丟失,constructor
會默認爲Object
瀏覽器
function F() {}; var f = new F; f.constructor == F // true F.prototype = {a: 1} var f = new F f.constructor == F // false
在構造函數F.prototype
沒有被重寫以前,構造函數F
就是新建立的對象f
的數據類型。當F.prototype
被重寫以後,原有的constructor
引用丟失, 默認爲 Object所以,爲了規範開發,在重寫對象原型時通常都須要從新給
constructor
賦值,以保證對象實例的類型不被篡改閉包
Object
的原型方法,調用該方法,默認返回當前對象的 [[Class]]
。這是一個內部屬性,其格式爲 [object Xxx]
,其中 Xxx
就是對象的類型Object.prototype.toString.call('') ; // [object String] Object.prototype.toString.call(11) ; // [object Number] Object.prototype.toString.call(true) ; // [object Boolean] Object.prototype.toString.call(Symbol()); //[object Symbol] Object.prototype.toString.call(undefined) ; // [object Undefined] Object.prototype.toString.call(null) ; // [object Null] Object.prototype.toString.call(new Function()) ; // [object Function] Object.prototype.toString.call([]) ; // [object Array]
null
表示"沒有對象",即該處不該該有值
典型用法:app
undefined
表示"缺乏值",就是此處應該有一個值,可是尚未定義
典型用法:
undefined
undefined
undefined
undefined
修改器方法:
訪問方法:
迭代方法:
undefined
true
,不然返回 falsetrue
,不然返回 falsetrue
的數組元素放進一個新數組中並返回更多方法請參考 MDN 傳送門
對象字面量
var obj = {}
Object 構造函數
var obj = new Object()
工廠模式
function Person(name, age) { var o = new Object() o.name = name; o.age = age; o.say = function() { console.log(name) } return o }
缺點: 每次經過Person
建立對象的時候,全部的say
方法都是同樣的,可是卻存儲了屢次,浪費資源
構造函數模式
function Person(name, age) { this.name = name this.age = age this.say = function() { console.log(name) } } var person = new Person('hello', 18)
構造函數模式隱試的在最後返回return this
因此在缺乏new
的狀況下,會將屬性和方法添加給全局對象,瀏覽器端就會添加給window
對象,能夠根據return this
的特性調用call
或者apply
指定this
原型模式
function Person() {} Person.prototype.name = 'hanmeimei'; Person.prototype.say = function() { alert(this.name); } Person.prototype.friends = ['lilei']; var person = new Person();
實現了方法與屬性的共享,能夠動態添加對象的屬性和方法。可是沒有辦法建立實例本身的屬性和方法,也沒有辦法傳遞參數
構造函數和原型組合
function Person(name, age) { this.name = name this.age = age } Person.prototype.say = function() { console.log(this.name) } var person = new Person('hello')
還有好幾種模式,感興趣的小夥伴能夠參考 紅寶書,大家確定知道的了!
淺拷貝
Array.prototype.slice()
也能夠完成對一個數組或者對象的淺拷貝Object.assign()
方法深拷貝
JSON.parse(JSON.stringify(目標對象)
,缺點就是隻能拷貝符合JSON
數據標準類型的對象簡單來講,閉包就是可以讀取其餘函數內部變量的函數
function Person() { var name = 'hello' function say () { console.log(name) } return say() } Person() // hello
因爲 JavaScript 特殊的做用域,函數外部沒法直接讀取內部的變量,內部能夠直接讀取外部的變量,從而就產生了閉包的概念
用途:
最大用處有兩個,一個是前面提到的能夠讀取函數內部的變量,另外一個就是讓這些變量的值始終保持在內存中
注意點:
因爲閉包會使得函數中的變量都被保存在內存中,內存消耗很大,因此不能濫用閉包,不然會形成網頁的性能問題,在IE中可能致使內存泄露
首先明確一點,JavaScript是基於原型的
每一個構造函數(constructor)都有一個原型對象(prototype),原型對象都包含一個指向構造函數的指針,而實例(instance)都包含一個指向原型對象的內部指針.
圖解:
prototype
屬性,這個屬性指向一個對象,也就是原型對象constructor
屬性,指向指向它的那個構造函數[[prototype]]
,指向它的原型對象那麼什麼是原型鏈:
JavaScript
中全部的對象都是由它的原型對象繼承而來。而原型對象自身也是一個對象,它也有本身的原型對象,這樣層層上溯,就造成了一個相似鏈表的結構,這就是原型鏈全部原型鏈的終點都是
Object
函數的prototype
屬性。Objec.prototype
指向的原型對象一樣擁有原型,不過它的原型是null
,而null
則沒有原型
function Animal() {} Animal.prototype.name = 'cat' Animal.prototype.age = 1 Animal.prototype.say = function() {console.log('hello')} var cat = new Animal() cat.name // cat cat.age // 1 cat.say() // hello
最簡單的繼承實現方式,可是也有其缺點
new
語句以後執行,不能放到構造器中function Animal() { this.species = "動物" } function Cat(name, age) { Animal.call(this) this.name = name this.age = age } var cat = new Cat('豆豆', 2) cat.name // 豆豆 cat.age // 2 cat.species // 動物
使用call或apply方法,將父對象的構造函數綁定在子對象上.
function Animal() { this.species = "動物" } function Cat(name){ Animal.call(this) this.name = name } Cat.prototype = new Animal() // 重寫原型 Cat.prototype.constructor = Cat
若是沒有Cat.prototype = new Animal()
這一行,Cat.prototype.constructor
是指向Cat
的;加了這一行之後,Cat.prototype.constructor
指向Animal
.這顯然會致使繼承鏈的紊亂(cat1明明是用構造函數Cat生成的),所以咱們必須手動糾正,將Cat.prototype
對象的constructor
值改成Cat
extends
繼承ES6新增繼承方式,Class 能夠經過extends關鍵字實現繼承
class Animal { } class Cat extends Animal { constructor() { super(); } }
使用extends
實現繼承,必須添加super
關鍵字定義子類的constructor
,這裏的super()
就至關於Animal.prototype.constructor.call(this)
固然,還有不少種實現繼承的方式,這裏就很少說了。而後,再推薦一波 紅寶書
這裏如今只是JavaScript
面試題中的一部分,後面是持續更新, 有須要的小夥伴能夠關注哦好了,週末愉快 [啊!結束了……]