來自 菜鳥 的 前端實習面經 大廠 春招實習生

寫在開頭

轉眼到了該實習的時間,或許還是自己不夠優秀把,感覺挺搞心態的,我的第一份投遞的公司直接就刷了我,我連面試的資格都沒有,當時看到“不匹配”三個字的時候,我頓時有點了難受,心態感覺被搞了一下。或許這就是現實把。

然後我獨自思考了5分鐘後,還是得從自己找找問題,我要想憑什麼其它公司就會招我,誰又會願意找一個萌新然後還要發錢給他呢? 想來還是自己不夠優秀,簡歷上也沒什麼好多要寫的,但是 我的追求不會放棄,我的野心依舊在,可能眼前才能支撐不了我的野心,不如冷靜下來沉心學習吧。

接下來的內容,是我這些天自己總結和整理的,關於前端實習面經,當然還會一直更新下去,直到我拿到讓自己滿意的 Offer !

以下就是本人整理的部分內容,希望對你會有一點幫助,加油吧,追夢的人!

HTML相關


html5有哪些新特性

新特性:

  • HTML5 現在已經不是 SGML 的子集,主要是關於圖像,位置,存儲,多任務等功能的增加。
  • 拖拽釋放(Drag and drop) API
  • 語義化更好的內容標籤(header,nav,footer,aside,article,section)
  • 音頻、視頻API(audio,video)
  • 畫布(Canvas) API
  • 地理(Geolocation) API
  • 本地離線存儲 localStorage 長期存儲數據,瀏覽器關閉後數據不丟失;
  • sessionStorage 的數據在瀏覽器關閉後自動刪除
  • 表單控件,calendar、date、time、email、url、search
  • 新的技術webworker, websocket, Geolocation
html5移除了哪些元素
  • 純表現的元素:basefont,big,center,font, s,strike,tt,u;
  • 對可用性產生負面影響的元素:frame,frameset,noframes;

詳細請閱讀:html5新特性

如何處理HTML5新標籤的瀏覽器兼容問題

IE8/IE7/IE6支持通過document.createElement方法產生的標籤,
可以利用這一特性讓這些瀏覽器支持HTML5新標籤,
當然最好的方式是直接使用成熟的框架、使用最多的是html5shim框架

  <!--[if lt IE 9]>
  <script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script>
  <![endif]-->
如何區分 HTML 和 HTML5

DOCTYPE聲明\新增的結構元素\功能元素

JS相關


Var和不Var有啥區別?

在一個函數中Var,在外部是訪問不道德,所以我們需要閉包
如果不用Var,就是全局作用域了,外部可以訪問,此時的上下文就是window

可迭代,意味着我能夠通過 for…in 循環來訪問該對象的所有屬性. 還能通過 Object.keys() 方法獲取該對象的所有屬性名.
可修改,意味着我能修改該對象的所有屬性的值,通過爲這些屬性賦予一個新值就能修改: ob.a = 1000;.
可配置,意味着我能修改屬性的行爲,讓該對象的屬性都是不可迭代的、不可修改的和不可配置的. 只有可配置的屬性才能通過 delete 被刪除.

深入:var與不var區別就在可配置屬性上,聲明一個全局變量,其實是給window增加一個屬性,由於window對象是全局對象,默認可不加,全局作用域下,window也可以用this來代替
“delete”不可以刪除那些可配置爲false的屬性,某些內置對象的屬性是不可配置的,比如通過變量聲明或者函數聲明創建的全局對象的屬性。

怎麼看一個屬性是對象自有的還是從原型鏈繼承下來的?

其實就是問in和hasOwnProperty()操作

原型鏈上繼承過來的屬性無法通過hasOwnProperty檢測到,返回false
in能檢測原型鏈的屬性,但for in通常卻不行

js對象能帶-嗎?

Object中的key規定了是字符串,但是加了- 就用不了.調用
因爲解釋器分不清是不是減號 -

關於閉包的問題

閉包指的是能夠訪問另一個函數作用域的函數,簡單來說,閉包就是一個函數,這個函數能夠訪問其它函數作用域中的變量。 eg:

function outer() {
     var  a = '變量1'
     var  inner = function () {
            console.info(a)
     }
    return inner    // inner 就是一個閉包函數,因爲他能夠訪問到outer函數的作用域
}

徹底弄懂JS閉包問題

數組去重

數組去重,數組扁平化優化

中間件

深入理解nodejs中Express的中間件

js有哪些數據類型

6中原始數據類型:

  • Number 表示數字類型
  • String 表示文本類型
  • Null 特指對象的值未設置
  • Undefined 沒有被賦值的變量的默認值
  • Boolean 表示邏輯實體,有true和false兩個值
  • Symbol 符號(Symbols)是ECMAScript 第六版中定義的。符號類型是唯一的並且不可修改

引用類型:Object

基本數據類型和引用數據類型有什麼區別

參考:基本數據類型與引用數據類型的區別

怎麼判斷不同的js數據類型
  • typeof 操作符:返回一個字符串,表示未經計算的操作數的類型
    typeof操作符對於簡單數據類型,返回其本身的數據類型,函數對象返回function,其它對象均返回Object
    null返回Object
  • instanceof :用來判斷A是否是B的實例,表達式爲 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類型

  • constructor:當一個函數被定義時,js引擎會爲其添加prototype原型,然後在prototype上添加一個constructor屬性,並讓其指向該函數的引用
    nullundefined是無效的對象,因此不會有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賦值,以保證對象實例的類型不被篡改
  • tostring :Object的原型方法,默認返回當前對象的【class】。這是一個內部屬性,其格式爲[Object xxxx] ,其中xxxx就是對象的類型
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]
undefined和null有什麼區別

null 表示沒有對象,即該出不該有值

典型用法:

  • 作爲函數的參數,表示該函數的參數不是對象
  • 作爲對象原型鏈的終點

undefined 表示缺少值,就是此處應該有一個值,但是還沒有定義

典型用法:

  • 變量被聲明瞭,但沒有賦值時,就等於undefined
  • 調用函數時,應該提供的參數沒有提供時,該參數等於undefined
  • 對象沒有賦值的屬性,該屬性的值爲undefined
  • 函數沒有返回值時,默認返回undefined

詳見: undefined和null的區別-阮一峯

== 和 === 的區別

“==” 就代表會先把兩端的變量試圖轉換成相同類型,然後再比較;

“===” 就代表會直接去比較類型是否相同,如果類型相同則繼續比較值是否相同。

舉個栗子:

使用 typeof bar === “object” 來確定 bar 是否是對象的潛在陷阱是什麼?如何避免這個陷阱?

儘管 typeof bar === “object” 是檢查 bar 是否對象的可靠方法,令人驚訝的是在JavaScript中 null 也被認爲是對象!

因此,令大多數開發人員驚訝的是,下面的代碼將輸出 true 控制檯:

要答全問題,還有其他兩件事情值得注意:

  • 首先,上述解決方案將返回 false,當 bar 是一個函數的時候。在大多數情況下,這是期望行爲,但當你也想對函數返回 true 的話,你可以修改上面的解決方案爲:

第二,上述解決方案將返回 true,當 bar 是一個數組(例如,當 var bar = [];)的時候。

在大多數情況下,這是期望行爲,因爲數組是真正的對象,但當你也想對數組返回 false 時,你可以修改上面的解決方案爲:

use strict是什麼意思?使用它區別是什麼?

use strict是一種ECMAscript 5 添加的(嚴格)運行模式,這種模式使得 Javascript 在更嚴格的條件下運行,
使JS編碼更加規範化的模式,消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行爲。

默認支持的糟糕特性都會被禁用,比如不能用with,也不能在意外的情況下給全局變量賦值;
全局變量的顯示聲明,函數必須聲明在頂層,不允許在非函數代碼塊內聲明函數,arguments.callee也不允許使用;
消除代碼運行的一些不安全之處,保證代碼運行的安全,限制函數中的arguments修改,嚴格模式下的eval函數的行爲和非嚴格模式的也不相同;
提高編譯器效率,增加運行速度;
爲未來新版本的Javascript標準化做鋪墊。

什麼是window對象? 什麼是document對象?
  • window對象

    在全局作用域中聲明的變量、函數都是window對象的屬性和方法。

    window對象是相對於web瀏覽器而言的,依賴於瀏覽器,在瀏覽器中全局對象指的就是window對象

  • document對象

    document對象是window對象的一個屬性,是顯示於窗口內的一個文檔。而window對象則是一個頂層對象,它不是另一個對象的屬性。document可以理解爲文檔,就是你的網頁,而window是你的窗口,就是你的瀏覽器包含的。

區別:
① window 指窗體。document指頁面。document是window的一個屬性。
② 用戶不能改變 document.location(因爲這是當前顯示文檔的位置)。但是,可以改變window.location (用其它文檔取代當前文檔)window.location本身也是一個對象,而document.location不是對象

數組對象有哪些常用方法
修改器方法:
  • pop(): 刪除數組的最後一個元素,並返回這個元素
  • push():在數組的末尾增加一個或多個元素,並返回數組的新長度
  • reverse(): 顛倒數組中元素的排列順序
  • shift(): 刪除數組的第一個元素,並返回這個元素
  • unshift(): 在數組的開頭增加一個或多個元素,並返回數組的新長度
  • sort(): 對數組元素進行排序,並返回當前數組
  • splice(): 在任意的位置給數組添加或刪除任意個元素
訪問方法:
  • concat(): 返回一個由當前數組和其它若干個數組或者若干個非數組值組合而成的新數組
  • join(): 連接所有數組元素組成一個字符串
  • slice(): 抽取當前數組中的一段元素組合成一個新數組
  • indexOf(): 返回數組中第一個與指定值相等的元素的索引,如果找不到這樣的元素,則返回 -1
  • lastIndexOf(): 返回數組中最後一個(從右邊數第一個)與指定值相等的元素的索引,如果找不到這樣的元素,則返回 -1
迭代方法:
  • forEach(): 爲數組中的每個元素執行一次回調函數,最終返回 undefined
  • every(): 如果數組中的每個元素都滿足測試函數,則返回 true,否則返回 false
  • some(): 如果數組中至少有一個元素滿足測試函數,則返回 true,否則返回 false
  • filter(): 將所有在過濾函數中返回 true 的數組元素放進一個新數組中並返回
  • map(): 返回一個由回調函數的返回值組成的新數組

更多請參考Array原文

js有哪幾種創建對象的方式

對象字面量

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.stringfy(目標對象)),缺點就是隻能拷貝符合JSON數據標準類型的對象

參考:js中深拷貝與淺拷貝詳

什麼是閉包,爲什麼要使用它

簡單來說,閉包就是能夠讀取其他函數內部變量的函數

function Person() {
    var name = 'hello'
    function say () {
        console.log(name)
    }
    return say()
}
Person() // hello
由於 JavaScript 特殊的作用域,函數外部無法直接讀取內部的變量,內部可以直接讀取外部的變量,從而就產生了閉包的概念

用途:

最大用處有兩個,一個是前面提到的可以讀取函數內部的變量,另一個就是讓這些變量的值始終保持在內存中

注意點:

由於閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致內存泄露

參考:js中的閉包

作用域的概念

內部環境可以通過作用域鏈來訪問外部環境的屬性和方法,但是,外部環境不能訪問內部環境的任何屬性和方法。注意,只能通過定義函數來延長作用域鏈條。

作用域鏈的作用主要用於查找標識符,當作用域需要查詢變量的時候會沿着作用域鏈依次查找,如果找到標識符就會停止搜索,否則將會沿着作用域鏈依次向後查找,直到作用域鏈的結尾。

介紹一下js中的原型,原型鏈,它們有何特點

首先明確一點,JavaScript 是基於原型的

每個構造函數(constructor)都有一個原型對象(prototype),原型對象都包含一個指向構造函數的指針,而實例(instance)都包含一個指向原型對象的內部指針.

圖解:

  • 每一個構造函數都擁有一個prototype屬性,這個屬性指向一個對象,也就是原型對象
  • 原型對象默認擁有一個constructor屬性,指向指向它的那個構造函數
  • 每個對象都擁有一個隱藏的屬性[[prototype]],指向它的原型對象

什麼是原型鏈:

JavaScript中所有的對象都是由它的原型對象繼承而來。而原型對象自身也是一個對象,它也有自己的原型對象,這樣層層上溯,就形成了一個類似鏈表的結構,這就是原型鏈

所有原型鏈的終點都是Object函數的prototype屬性。Objec.prototype指向的原型對象同樣擁有原型,不過它的原型是null,而null則沒有原型

清楚了原型鏈的概念,我們就能更清楚地知道屬性的查找規則,比如前面的 p 實例屬性.如果自身和原型鏈上都不存在這個屬性,那麼屬性最終的值就是 undefined ,如果是方法就會拋出錯誤

參考:js中原型與原型鏈

js如何實現繼承

原型鏈繼承

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)

參考:js中的繼承

new操作符具體做了什麼
  • 創建一個空對象,並且 this 變量引用該對象,同時還繼承了該函數的原型
  • 屬性和方法被加入到 this 引用的對象中
  • 新創建的對象由 this 所引用,並且最後隱式的返回 this
同步和異步的區別,怎麼異步加載 JavaScript

同步模式

又稱爲阻塞模式,javascript 在默認情況下是會阻塞加載的。當前面的 javascript 請求沒有處理和執行完時,會阻止瀏覽器的後續處理

異步模式

異步加載又叫非阻塞,瀏覽器在下載執行 js 同時,還會繼續進行後續頁面的處理

異步加載 JavaScript

  • 動態添加 script 標籤
  • defer
  • async
defer屬性和async都是屬於 script 標籤上面的屬性,兩者都能實現 JavaScript 的異步加載。不同之處在於:async 在異步加載完成的時候就馬上開始執行了,defer 會等到 html 加載完畢之後再執行
跨域問題的產生,怎麼解決它
由於瀏覽器的 同源策略,在出現 域名、端口、協議有一種不一致時,就會出現跨域,屬於瀏覽器的一種安全限制。

解決跨域問題有很多種方式,常用的就是以下幾種:

  • jsonp 跨域:動態創建script,再請求一個帶參網址實現跨域通信.缺點就是隻能實現 get 一種請求
  • document.domain + iframe跨域:兩個頁面都通過js強制設置document.domain爲基礎主域,就實現了同域.但是僅限主域相同,子域不同的跨域應用場景
  • 跨域資源共享CORS:只服務端設置Access-Control-Allow-Origin即可,前端無須設置,若要帶cookie請求:前後端都需要設置
  • nginx反向代理接口跨域:同源策略是瀏覽器的安全策略,不是HTTP協議的一部分。服務器端調用HTTP接口只是使用HTTP協議,不會執行JS腳本,不需要同源策略,也就不存在跨越問題
  • WebSocket協議跨域
談談對 this 的理解

在 JavaScript 中,研究 this 一般都是 this 的指向問題,核心就是 this 永遠指向最終調用它的那個對象,除非改變 this 指向或者箭頭函數那種特殊情況

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

test() // window

var obj = {
  foo: function () { console.log(this.bar) },
  bar: 1
};

var foo = obj.foo;
var bar = 2;

obj.foo() // 1
foo() // 2

// 函數調用的環境不同,所得到的結果也是不一樣的
關於this指向問題

參考:關於this指向的問題

apply()、call()和 bind() 是做什麼的,它們有什麼區別

相同點:三者都可以改變 this 的指向

不同點:

  • apply 方法傳入兩個參數:一個是作爲上下文的對象,另一個是作爲函數所組成的數組
var obj = {
    name : 'sss'
}

function func(firstName, lastName){
    console.log(firstName + ' ' + this.name + ' ' + lastName);
}

func.apply(obj, ['A', 'B']);    // A sss B
  • call 方法第一個參數也是作爲作爲函數上下文的對象,但是後面傳入的是一個參數列表,而不是單個數組
var obj = {
    name: 'sss'
}

function func(firstName, lastName) {
    console.log(firstName + ' ' + this.name + ' ' + lastName);
}

func.call(obj, 'C', 'D');       // C sss D
  • bing接受的參數有兩個部分,第一個參數是作爲函數上下文的對象,第二部分參數是一個列表,可以接受多個參數
var obj = {
    name: 'sss'
}

function func() {
    console.log(this.name);
}

var func1 = func.bind(null, 'xixi');
func1();

apply、call 方法都會使函數立即執行,因此它們也可以用來調用函數

bind 方法不會立即執行,而是返回一個改變了上下文 this 後的函數。而原函數 func 中的 this 並沒有被改變,依舊指向全局對象 window

bind 在傳遞參數的時候會將自己帶過去的參數排在原函數參數之前

function func(a, b, c) {
    console.log(a, b, c);
}
var func1 = func.bind(this, 'xixi');
func1(1,2) // xixi 1 2
什麼是內存泄漏,哪些操作會造成內存泄漏

內存泄漏:是指一塊被分配的內存既不能使用,又不能回收,直到瀏覽器進程結束

可能造成內存泄漏的操作:

  • 意外的全局變量
  • 閉包
  • 循環引用
  • 被遺忘的定時器或者回調函數

你可能還需要知道 垃圾回收機制

什麼是事件代理,它的原理是什麼

事件代理:通俗來說就是將元素的事件委託給它的父級或者更外級元素處理

原理:利用事件冒泡機制實現的

優點:只需要將同類元素的事件委託給父級或者更外級的元素,不需要給所有元素都綁定事件,減少內存空間佔用,提升性能; 動態新增的元素無需重新綁定事件

對AMD和CMD的理解,它們有什麼區別

AMD和CMD都是爲了解決瀏覽器端模塊化問題而產生的,AMD規範對應的庫函數有 Require.js,CMD規範是在國內發展起來的,對應的庫函數有Sea.js

AMD和CMD最大的區別是對依賴模塊的執行時機處理不同

1、AMD推崇依賴前置,在定義模塊的時候就要聲明其依賴的模塊

2、CMD推崇就近依賴,只有在用到某個模塊的時候再去require

AMD-中文版 CMD-規範

對ES6的瞭解

ECMAScript 6.0 是 JavaScript 語言的下一代標準

新增的特性:

  • 聲明變量的方式 let const
  • 變量解構賦值
  • 字符串新增方法 includes() startsWith() endsWith() 等
  • 數組新增方法 Array.from() Array.of() entries() keys() values() 等
  • 對象簡潔寫法以及新增方法 Object.is() Object.assign() entries() keys() values()等
  • 箭頭函數、rest 參數、函數參數默認值等
  • 新的數據結構: Set 和 Map
  • Proxy
  • Promise對象
  • async函數 await命令
  • Class類
  • Module 體系 模塊的加載和輸出方式

參考 ES6入門-阮一峯

箭頭函數有什麼特點

ES6 允許使用箭頭=> 定義函數

var f = v => v;

// 等同於
var f = function (v) {
  return v;
}

注意點:

  • 函數體內的 this 對象,就是定義時所在的對象,而不是使用時所在的對象
  • 不可以當作構造函數,也就是說,不可以使用 new 命令,否則會拋出一個錯誤
  • 不可以使用 arguments 對象,該對象在函數體內不存在。如果要用,可以用 rest 參數代替
Promise 對象的瞭解

Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大.所謂 Promise ,簡單說就是一個容器,裏面保存着某個未來纔會結束的事件(通常是一個異步操作)的結果 —— ES6 入門-阮一峯

Promise 對象代表一個異步操作,有三種狀態:pending(進行中)、fulfilled(已成功)和 rejected(已失敗)。只有異步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態

特點:

  • 對象的狀態不受外界影響
  • 一旦狀態改變,就不會再變,任何時候都可以得到這個結果
  • Promise 新建後就會立即執行
const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 異步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
})

Promise 實例生成以後,可以用 then 方法分別指定 resolved 狀態和 rejected 狀態的回調函數

promise.then(function(value) {
  // success
}, function(error) {
  // failure
})

then 方法返回的是一個新的Promise實例

Promise.prototype.catch 用於指定發生錯誤時的回調函數,具有冒泡性質,會一直向後傳遞,直到被捕獲爲止。也就是說,錯誤總是會被下一個catch語句捕獲

getJSON('/post/1.json').then(function(post) {
  return getJSON(post.commentURL);
}).then(function(comments) {
  // some code
}).catch(function(error) {
  // 處理前面三個Promise產生的錯誤
});

catch 方法返回的還是一個 Promise 對象,因此後面還可以接着調用 then 方法

出去上述方法,Promise 還有其他用法,小夥伴們可以在這裏查看大佬寫的文章 ES6入門-阮一峯

async 函數以及 await 命令

async 函數是什麼?一句話,它就是 Generator 函數的語法糖

語法糖是指在不影響功能的情況下,添加某種方法實現同樣的效果,從而方便程序開發.Vue.js的v-bind和v-on指令都提供了語法糖,也可以說是縮寫。

async 特點:

  • async 函數返回一個 Promise 對象,可以使用 then 方法添加回調函數。當函數執行的時候,一旦遇到 await 就會先返回,等到異步操作完成,再接着執行函數體內後面的語句

  • async 函數內部 return 語句返回的值,會成爲 then 方法回調函數的參數

  • async 函數返回的 Promise 對象,必須等到內部所有 await 命令後面的 Promise 對象執行完,纔會發生狀態改變,除非遇到 return 語句或者拋出錯誤

  • async 函數內部拋出錯誤,會導致返回的 Promise 對象變爲 reject 狀態。拋出的錯誤對象會被 catch 方法回調函數接收到

function timeout(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value);
}

asyncPrint('hello world', 50);

await 命令: await 命令後面是一個 Promise 對象,返回該對象的結果。如果不是 Promise 對象,就直接返回對應的值

async function f() {
  // 等同於
  // return 123;
  return await 123;
}

f().then(v => console.log(v))
// 123
await 命令後面是一個thenable對象(即定義then方法的對象),那麼await會將其等同於 Promise 對象.也就是說就算一個對象不是Promise對象,但是隻要它有then這個方法, await 也會將它等同於Promise對象

使用注意點:

  • await 命令後面的 Promise 對象,運行結果可能是 rejected,所以最好把 await 命令放在 try…catch 代碼塊中
  • 多個 await 命令後面的異步操作,如果不存在繼發關係,最好讓它們同時觸發
  • await 命令只能用在 async 函數之中,如果用在普通函數,就會報錯

參考:async 和 await

export 與 export default有什麼區別

export 與 export default 均可用於導出常量、函數、文件、模塊等

在一個文件或模塊中,export、import 可以有多個,export default 僅有一個

通過 export 方式導出,在導出時要加 { },export default 則不需要

使用 export default命令,爲模塊指定默認輸出,這樣就不需要知道所要加載模塊的變量名; export 加載的時候需要知道加載模塊的變量名

export default 命令的本質是將後面的值,賦給 default 變量,所以可以直接將一個值寫在 export default 之後

前端性能優化

參考:雅虎14條前端性能優化

對JS引擎執行機制的理解

首選明確兩點:

JavaScript 是單線程語言

JavaScript 的 Event Loop 是 JS 的執行機制, 也就是事件循環

console.log(1)
    
setTimeout(function(){
    console.log(2)
},0)

console.log(3)

// 1 3 2

JavaScript 將任務分爲同步任務和異步任務,執行機制就是先執行同步任務,將同步任務加入到主線程,遇到異步任務就先加入到 event table ,當所有的同步任務執行完畢,如果有可執行的異步任務,再將其加入到主線程中執行

視頻詳解, 傳送門

setTimeout(function(){console.log(1);},0);
new Promise(function(resolve){
     console.log(2);
     for(var i = 0; i < 10000; i++){
         i == 99 && resolve();
     }
 }).then(function(){
     console.log(3)
 });
 
 console.log(4);
 
 // 2 4 3 1

在異步任務中,定時器也屬於特殊的存在。有人將其稱之爲 宏任務、微任務,定時器就屬於宏任務的範疇。

詳情:這次,徹底弄懂js執行機制

CSS相關


CSS 選擇符有哪些

1.id選擇器( # myid)

2.類選擇器(.myclassname)

3.標籤選擇器(div, h1, p)

4.相鄰選擇器(h1 + p)

5.子選擇器(ul > li)

6.後代選擇器(li a)

7.通配符選擇器( * )

8.屬性選擇器(a[rel = “external”])

9.僞類選擇器(a: hover, li:nth-child)

不可繼承的樣式

border padding margin width height

優先級算法如何計算

優先級:

!important > id > class > tag

important 比 內聯優先級高,但內聯比 id 要高

盒模型概念

個人理解是整個html頁面就是無數個通過特定的佈局結合在一起的,每個盒子包括內容(content)、內邊距(padding)、邊框(border)、外邊距(margin)。

這一次,徹底看懂 CSS 盒模型(圖文並茂)

參考:前端面試必備的css盒子模型

高度塌陷問題

父元素的高度,默認被子元素撐開。例如子元素設置浮動,則會導致其完全脫離文檔流,子元素脫離文檔流將無法撐開父元素,導致父元素的高度丟失,就是我們所說的高度塌陷問題。

例如,我們想要的界面是如下:

然而,可能會出現如下情況:

解決辦法:
參考:前端基礎問題 – 高度塌陷問題詳解(面試重點問題)

position的幾個屬性
  • static 默認,指示元素出現在正常的文檔流中
  • relative(相對定位) 相對於該元素在文檔流中的正常位置進行偏移定位,佔用文檔流。常用作絕對定位元素的容器塊。
  • absolute(絕對定位)較少直接單獨使用在正常的文檔流中,而是配合relative來進行一些更靈活更精確的定位。換言之,就是絕對定位主要運行於進行了相對定位的元素框架層裏面,然後依據該層的最左上點作爲基點進行便宜。常用作動畫結構。
  • fixed(固定定位)相對於瀏覽器窗口的最左上點作爲基點進行偏移定位,應用比較少,主要是運用與瀏覽器貼邊定位。和絕對定位一樣可以用在固定定位的框架層裏面。常用作漂浮廣告,返回頂部。
  • z-index屬性,使用以上三種定位後,都會使正常的文檔流在一定程度上發生變化,造成元素顯示重疊問題,也就是上文所提及到的塌陷問題。使用該屬性能夠設置優先級,數值越大,優先級越高,該屬性只對使用了定位的元素有效。

新增的屬性:

  • sticky(粘性佈局) 結合了相對和固定定位兩種,常見使用場景是實現頭部導航欄固定。

參考:position屬性值(面試必考)

CSS 中 display 的 block,inline,inline-block 這三個屬性有什麼區別
  • display: block
    1.block元素會獨佔一行,多個bolck元素會各自新起一行。默認情況下,block元素寬度會自動填滿其父元素寬度。
    2.可以設置width、height、padding、margin屬性

  • display: inline
    1.inline元素不會獨佔一行,多個相鄰的元素會排在同一行內,直到排不下才會換新一行。寬度會隨元素內容變化而變化
    2.無法設置width、height,padding和水平方向外邊距margin會產生邊距效果,其它的不會。

  • display: inline-block
    1.簡單說是將對象呈現爲inline對象,但對象的內容作爲block對象呈現。比如我們可以給一個link(a元素)inline-block屬性值,使其既具有block的寬度高度特性又具有inline的同行特性。

參考:CSS 中 display 的 block,inline,inline-block

另附display其它值:

none:設置元素不可見;
flex:開啓彈性佈局;
table:作爲塊級表格顯示;
list-item:像塊級元素一樣顯示,並添加樣式列表標記;
inherit:繼承父元素的display屬性;

常見的塊級元素和內聯元素有哪些
  • 塊級元素:div、 form 、 table 、p 、pre、 h1 ~ h6 、dl 、ol 、ul等
  • 內聯元素:span、 a 、strong、 em 、label 、input 、select 、textarea 、 img 、br等
解釋盒模型寬高值得計算方式,邊界塌陷,負值作用,box-sizing概念
  1. 盒模型:IE 678 下(不添加doctype) 使用ie盒模型,寬度 = 邊框 + padding + 內容寬度; chrom、IE9+、(添加doctype) 使用標準盒模型, 寬度 = 內容寬度。
  2. box-sizing : 爲了解決標準黑子和IE盒子的不同,CSS3增添了盒模型屬性box-sizing,content-box(默認),border-box 讓元素維持IE傳統盒子模型, inherit 繼承 父盒子模型;
  3. 邊界塌陷:塊元素的 top 與 bottom 外邊距有時會合並(塌陷)爲單個外邊距(合併後最大的外邊距),這樣的現象稱之爲 外邊距塌陷。
  4. 負值作用:負margin會改變浮動元素的顯示位置,即使我的元素寫在DOM的後面,我也能讓它顯示在最前面。
BFC(Block Formatting Context) 是什麼?應用?

BFC 就是 ‘塊級格式上下文’ 的格式,創建了BFC的元素就是一個獨立的盒子,不過只有BLock-level box可以參與創建BFC,它規定了內部的Bloc-level Box 如何佈局,並且與這個獨立盒子裏的佈局不受外部影響,當然它也不會影響到外面的元素。

應用場景:

  1. 解決margin疊加的問題
  2. 用於佈局(overflow: hidden),BFC不會與浮動盒子疊加。
  3. 用於清除浮動,計算BFC高度。
如何實現瀏覽器內多個標籤頁之間的通信

調用localstorge、cookies等本地存儲方式

爲什麼要清除浮動?清除浮動的方式?
  • 清除浮動主是要爲了解決父級元素因爲子級浮動引起內部高度爲0的問題(父級沒有高度的情況);很多情況下不方便給父親高度,比如新聞,不知道新聞裏面多少字,不方面給高度,一般是讓裏面的內容自動撐開高度。這個時候就需要清除浮動,用clear 屬性:清除浮動
  • 清除方式:
    1、父級盒子定義一個height
    2、父級盒子定義overflow:hidden/auto;
    3、額外標籤法:在浮動盒子的後面加一個空標籤,例如
.clear{
    clear:both;
}

4、使用after僞元素清除浮動

.clearfix:after{
    display:block; /*  轉換爲塊級元素*/
    content:".";  /*  內容爲小點,儘量加不要空,防止舊版本有空隙*/  
    height:0; /*  高度爲0*/  
    visibility:hidden;/* 隱藏小點*/
    clear:both;
}
.clearfix{
    *zoom:1; /*  *代表IE6和IE7能識別的特殊符號,帶有這個*的屬性,只有IE6和IE7才執行,zoom就是IE6和IE7清除浮動的方法,IE6和IE7瀏覽器的處理方式,所以必須加上*/
}

5、使用before和after雙僞元素清除法

.clearfix:before,.clearfix:after{
    display:table; /*  轉換爲塊級元素*/
    content:"";  /*  爲空*/  
}
.clearfix:after{
   clear:both;
}
.clearfix{
    *zoom:1;
}
CSS3有哪些新特性
  • 實現圓角border-radius,陰影box-shadow,邊框圖片border-image
  • 對文字加特效text-shadow,強制文本換行word-wrap,線性漸變linear-gradient
  • 實現旋轉transform:rotate(90deg),縮放scale(0.85,0.90),translate(0px,-30px)定位,傾斜- skew(-9deg,0deg);
  • 增加了更多的CSS選擇器、多背景、rgba()
  • 唯一引入的僞元素是::selection;
  • 實現媒體查詢@media,多欄佈局flex
  • 過渡transition,動畫animation
盒子水平居中方式
  • 將margin-left和margin-right設置爲auto,或者margin:0,auto;(父盒子必須有高度)
  • 先讓盒子向左移動父盒子寬度的一半,再往回移動自身寬度的一半
  • 先把盒子轉換成inline-block +,然後text-align:center,使盒子水平居中
  • 使用絕對定位
div{
    position:absolute;
    width:100px;
    height:100px;
    left:50%;
    margin-left:-50px;
}
盒子垂直居中方式
  • 使用margin計算盒子的上下邊距,使其垂直居中
  • 將盒子轉換成display:table-cell,再vertical-align:middle;使盒子垂直居中
  • 先讓盒子向下移動父盒子高度的一半,再往回移動自身高度的一半
盒子垂直水平居中方式
  • 使用絕對定位 + left:50%,top: 50% + margin-left:(自身寬度的一半),margin-top:(自身高度的一半)
  • 使用絕對定位 + left:50% ,top: 50%+ translate(-50%,-50%)
  • 使用絕對定位 + left: 0,right: 0, top: 0, bottom: 0 + margin:auto
  • 使用彈性盒子佈局,給父標籤設置屬性,display: flex; justify-content: center; (水平居中)align-items: center;(垂直居中)
opacity和rgba的區別
  • opacity
    opacity是一個屬性,有opacity屬性的所有後代元素都會繼承 opacity 屬性
.box{
     opacity:0.4; //取值從 0.0 (完全透明)到 1.0(完全不透明)
}
  • rgba
    rgba是一個屬性值,語法爲rgba(r,g,b,a);rgba只會作用於它本身,不會作用於子元素上
.box{
     background: rgba(0,0,255,0.4); // 不限於背景顏色,可以是文字顏色,陰影等
}
CSS隱藏元素的幾種方法(至少說出三種)
  • Opacity:元素本身依然佔據它自己的位置並對網頁的佈局起作用。它也將響應用戶交互;
  • Visibility:與 opacity 唯一不同的是它不會響應任何用戶交互。此外,元素在讀屏軟件中也會被隱藏;
  • Display:display 設爲 none 任何對該元素直接打用戶交互操作都不可能生效。此外,讀屏軟件也不會讀到元素的內容。這種方式產生的效果就像元素完全不存在;
  • Position:不會影響佈局,能讓元素保持可以操作;
  • Clip-path:clip-path 屬性還沒有在 IE 或者 Edge 下被完全支持。如果要在你的 clip-path 中使用外部的 SVG 文件,瀏覽器支持度還要低;
請描述一下cookies,sessionStorage和localStorage的區別?

相同點:都會在瀏覽器端保存,有大小和同源限制。

不同點:
1、cookie會隨請求發送到服務器,作爲會話表示,服務器可修改cookie。web storage不會隨請求發送到服務器。
2、cookie有path的概念,子路徑可以訪問父路徑的cookie,父路徑不可以訪問子路徑的cookie。
3、有效期: cookie在設置的有效期內有效,默認爲瀏覽器關閉消失。sessionStorage在會話窗口關閉後失效,localStorage長期有效,需主動刪除。
4、sessionStorage不能共享,localStorage在同源文檔之間可以共享,cookie在同源且符合path規則的文檔之間可以共享。
5、localStorage的修改會觸發其他文檔的update事件。
6、cooie有secure屬性要求HTTPS傳輸。
7、瀏覽器不能保存超過300個cookie,單個服務器不能超過20個,每個cookie不能超過4k。webStorage可以支持5M的存儲。

css文件引入的方式有哪些?

引入方式3種:行內添加定義style屬性值,頁面頭部內內嵌在style標籤中調用和外鏈調用css文件

link和@import有什麼區別?

link屬於XHTML標籤,除了加載CSS外,還能用於定義RSS, 定義rel連接屬性等作用;而

@import是CSS提供的,只能用於加載CSS;

頁面被加載的時,link會同時被加載,而@import引用的CSS會等到頁面被加載完再加載;
import是CSS2.1 提出的,只在IE5以上才能被識別,而link是XHTML標籤,無兼容問題;

常見的瀏覽器內核有哪些?

Trident內核:IE,MaxThon,TT,The World,360,搜狗瀏覽器等。[又稱MSHTML]Gecko內核:Netscape6及以上版本,FF,MozillaSuite/SeaMonkey等

Presto內核:Opera7及以上。 [Opera內核原爲:Presto,現爲:Blink;]

Webkit內核:Safari,Chrome等。 [ Chrome的:Blink(WebKit的分支)]

簡述前端性能優化的方式

1、減少DOM操作
2、部署前,圖片壓縮,代碼壓縮
3、優化js代碼結構,減少冗餘代碼
4、減少http請求,合理設置HTTP緩存
5、使用內容分發cdn加速
6、靜態資源緩存
7、圖片延遲加載

對前端工程化的理解

開發規範
模塊化開發
組件化開發
開發倉庫
性能優化
項目部署
開發流程
開發工具

Vue


Vue生命週期
前端框架(framework ) 與 庫(library) 怎麼區別

庫,更多是一個封裝好的特定集合,提供給開發者使用,而且是特定與某一方面的集合(方法和函數),庫沒有控制權,控制權在使用者手中

前端框架,顧名思義就是一套架構,控制權在框架本身,使用者需按照框架的某種規範進行開發

mvvm mvc是什麼區別 原理

MVC(Model-View-Controller)

MVC是比較直觀的架構模式,用戶操作->View(負責接收用戶的輸入操作)->Controller(業務邏輯處理)->Model(數據持久化)->View(將結果反饋給View)。

MVC使用非常廣泛,比如JavaEE中的SSH框架

MVVM(Model-View-ViewModel)

如果說MVP是對MVC的進一步改進,那麼MVVM則是思想的完全變革。它是將“數據模型數據雙向綁定”的思想作爲核心,因此在View和Model之間沒有聯繫,通過ViewModel進行交互,而且Model和ViewModel之間的交互是雙向的,因此視圖的數據的變化會同時修改數據源,而數據源數據的變化也會立即反應view。

從輸入URL到頁面加載發生了什麼?【經典】

參考:前端經典面試題: 從輸入URL到頁面加載發生了什麼?

html是怎麼渲染的

參考:前端面試之4-1 渲染機制

計算機網絡


tcp和udp協議

tcp屬於傳輸層,ip屬於網絡層,http是應用層

tcp提供面向連接的傳輸,通信前要先建立連接(三次握手機制),udp提供無連接的傳輸,通信前不需要建立連接

tcp提供可靠(有序,無差錯,不丟失,不重複)的傳輸,udp提供不可靠的傳輸。

tcp面向字節流的傳輸,因此它可將信息分割成組,並在接收端將其重組,udp面向數據報的傳輸,沒有分組開銷

tcp提供擁塞控制和流量控制機制,udp不提供

http和https的區別

首先,我們的網站的URL分爲兩個部分:通信協議和域名地址。
簡單來說,域名地址表示不同的頁面
網站中的通信協議一般就是http和https協議

http協議是一種明文數據傳輸的協議,存在安全隱患。
而https協議是在http基礎上增加了數據加密,在數據傳輸之前,對數據進行加密,然後再發送服務器。這樣,就算傳輸過程中被截獲,但數據時加密了的,所以個人信息時安全的。

另外,還有的區別就是當訪問https的網站時,地址欄會顯示“安全鎖”,其次,對於百度和谷歌搜索引擎的話,https更加佔有優勢。

tcp三次握手與四次揮手

tcp三次握手:

起初A和B都處於close關閉狀態
B創建tcb,初遇listen收聽狀態,等待A請求

第一次握手:A創建tcb,發送連接請求,進入syn-sent同步已發送狀態。
第二次握手:B收到連接請求,向A發送確認和連接請求,進入syn-rcvd同步收到狀態。
第三次握手:A收到B的確認和連接請求後,向B發出確認,A進入established已連接狀態。

B收到A的確認收到進入established已連接狀態

參考:面試問題之計算機網絡:TCP三次握手四次揮手

http協議的請求方法

http請求方法一般有8種:GET、HEAD、PUT、DELETE、POST、OPTIONS、TRACE、CONNECT

  • get 最常見,發送一個請求來獲取服務器上的某一資源。資源通過一組http頭和呈現數據(如html文本,或者圖片視頻等)返回給客戶端。
  • head 和get本質一樣,不過返回的僅僅是http頭,區別是如果是判斷某個資源是否存在,通常使用head進行判斷更加明確。
  • put 和post相似,都是向服務器發送數據,但put通常指定了資源的存放位置,然而post位置是由服務器來決定的。
  • delete 刪除某一個資源,請求服務器刪除request-url所標識的資源。
  • post 向服務器提交數據。用途廣泛,幾乎所有提交操作都可以完成。post向指定資源提交數據進行請求處理(提交表單、上傳文件),有可能導致新資源的建立或原資源的修改
  • options 很少使用,獲取當前url所支持的方法,若請求成功,會在http頭包含一個名爲“allow”的頭,值是所支持的方法,如“get、post”等
  • trace 回顯服務器收到的請求,用於測試和診斷。
  • connect http/1.1協議中將連接改爲管道方式的代理服務器。
get和post有什麼區別
  • get是客戶端向服務器發送請求網頁頁面的請求,請求獲取服務器上的某一資源。post是客戶端向服務器上傳一些文件的請求,向服務器提交數據。
  • get請求參數會在url後進行傳遞,請求數據會附在url之後,以?分割url和傳輸數據,參數一件以&相連等等。get請求提交數據不安全,數據置於請求行,客戶端地址欄可見。而post方法提交數據安全,數據置於消息主體內,客戶端不可見。
  • get傳輸的數據有大小限制,因爲是通過url來提交數據的。而post提交的數據大小沒有限制。
  • get請求的數據會被瀏覽器緩存起來,用戶名和密碼將明文出現在url中,其他人可以查閱瀏覽歷史記錄,不安全。在服務器端,用Request.QueryString來獲取get方式提交來的數據。post表示可能修改服務器上的資源請求,在服務器端,用post方法提交的數據,只能用Request.Form來獲取。

操作系統


進程和線程的區別

進程:在操作系統中,能夠獨立運行,並且作爲資源分配的基本單位。它表示運行中的程序。
線程:是進程中的一個實例,作爲系統調度和分派的基本單位。是進程中的一段序列,能夠完成進程中的一個功能。

兩者的區別和聯繫:

  • 同一個進程可以包含多個線程,一個進程至少包含一個線程,一個線程只能存在於一個進程中。
  • 同一個進程下的所有線程能共享該進程下的資源
  • 進程結束後,該進程下的所有線程都會銷燬,而一個線程的結束不會影響同一進程下的其它線程
  • 線程是輕量級的進程,它的創建及銷燬所需的時間比進程小得多,所有操作系統的執行功能都是通過創建線程來完成的。
  • 線程在執行時是同步和互斥的,因爲他們共享同一個進程下的資源
  • 在操作系統中,進程是擁有系統資源的獨立單元,它可以擁有自己的資源。一般而言,線程不具有自己的資源,但能夠訪問隸屬進程的資源。
同步和異步的區別

同步就是發送請求後,等待服務器返回結果,纔會執行下一步。異步則是不等服務器返回,直接並行執行下一步,服務器返回結果會通過處理回調函數執行。

同步是阻塞模式,異步是非阻塞模式

阻塞和非阻塞的區別

應用進程請求I/O操作時,如果數據未準備好,請求立即返回就是非阻塞,不立即返回就是阻塞。
簡單來說,就是做一件事如果不能立即獲得返回,需要等待,就是阻塞。否則就是非阻塞

數據庫

Mysql中主鍵與外鍵的區別

主鍵:唯一標識一條記錄,保證不重複不爲空,保證數據完整性
外鍵:某表的外鍵是另一張表的主鍵,可以重複,可以爲空,用來和其他表建立聯繫。
問題:爲什麼要設置外鍵,可以通過where語句查詢也是一樣?
當刪除了設置外鍵的主鍵後,所有的外鍵都會被自動刪除,例如:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章