1.apply,call,bind有什麼區別?javascript
三者均可以把一個函數應用到其餘對象上,apply,call是直接執行函數調用,bind是綁定,執行須要再次調用。 html
apply和call的區別是apply接受數組做爲參數,而call是接受逗號分隔的無限多個參數列表。前端
代碼以下:vue
function Person() { } Person.prototype.sayName() { alert(this.name); } var obj = {name: 'michaelqin'}; // 注意這是一個普通對象,它不是Person的實例 // 1) apply Person.prototype.sayName.apply(obj, [param1, param2, param3]); // 2) call Person.prototype.sayName.call(obj, param1, param2, param3); // 3) bind var liaoke = Person.prototype.sayName.bind(obj); liaoke ([param1, param2, param3]); // bind須要先綁定,再執行 liaoke (param1, param2, param3); // bind須要先綁定,再執行
2.defineProperty,hasOwnProperty,isEnumerable都是作什麼用的?java
Object.defineProperty(obj,prop,descriptor)用來給對象定義屬性,有value,writeable,enumerable,set/get等,node
hasOwnProperty用於檢查某一屬性是否是存在於對象自己,react
isEnumerable用來檢測某一屬性是否可遍歷,也就是能不能用for...in循環來取到。git
3.JS經常使用設計模式的實現思路(單例、工廠、代理、裝飾、觀察者模式等)angularjs
// 1) 單例: 任意對象都是單例,無須特別處理 var obj = {name: 'michaelqin', age: 30}; // 2) 工廠: 就是一樣形式參數返回不一樣的實例 function Person() { this.name = 'Person1'; } function Animal() { this.name = 'Animal1'; } function Factory() {} Factory.prototype.getInstance = function(className) { return eval('new ' + className + '()'); } var factory = new Factory(); var obj1 = factory.getInstance('Person'); var obj2 = factory.getInstance('Animal'); console.log(obj1.name); // Person1 console.log(obj2.name); // Animal1 // 3) 代理: 就是新建個類調用老類的接口,包一下 function Person() { } Person.prototype.sayName = function() { console.log('michaelqin'); } Person.prototype.sayAge = function() { console.log(30); } function PersonProxy() { this.person = new Person(); var that = this; this.callMethod = function(functionName) { console.log('before proxy:', functionName); that.person[functionName](); // 代理 console.log('after proxy:', functionName); } } var pp = new PersonProxy(); pp.callMethod('sayName'); // 代理調用Person的方法sayName() pp.callMethod('sayAge'); // 代理調用Person的方法sayAge() // 4) 觀察者: 就是事件模式,好比按鈕的onclick這樣的應用. function Publisher() { this.listeners = []; } Publisher.prototype = { 'addListener': function(listener) { this.listeners.push(listener); }, 'removeListener': function(listener) { delete this.listeners[listener]; }, 'notify': function(obj) { for(var i = 0; i < this.listeners.length; i++) { var listener = this.listeners[i]; if (typeof listener !== 'undefined') { listener.process(obj); } } } }; // 發佈者 function Subscriber() { } Subscriber.prototype = { 'process': function(obj) { console.log(obj); } }; // 訂閱者 var publisher = new Publisher(); publisher.addListener(new Subscriber()); publisher.addListener(new Subscriber()); publisher.notify({name: 'michaelqin', ageo: 30}); // 發佈一個對象到全部訂閱者 publisher.notify('2 subscribers will both perform process'); // 發佈一個字符串到全部訂閱者
3.字符串經常使用的十個函數ajax
charAt() // 返回在指定位置的字符。 concat() // 鏈接字符串。 fromCharCode() // 從字符編碼建立一個字符串。 indexOf() // 檢索字符串。 match() // 找到一個或多個正則表達式的匹配。 replace() // 替換與正則表達式匹配的子串。 search() // 檢索與正則表達式相匹配的值。 slice() // 提取字符串的片段,並在新的字符串中返回被提取的部分。 split() // 把字符串分割爲字符串數組。 substr() // 從起始索引號提取字符串中指定數目的字符。 substring() // 提取字符串中兩個指定的索引號之間的字符。 toLocaleLowerCase() // 把字符串轉換爲小寫。 toLocaleUpperCase() // 把字符串轉換爲大寫。 toLowerCase() // 把字符串轉換爲小寫。 toUpperCase() // 把字符串轉換爲大寫。 toString() // 返回字符串。 valueOf() // 返回某個字符串對象的原始值。
4.如何判斷一個變量是對象仍是數組
function isObjArr(variable){ if (Object.prototype.toString.call(value) === "[object Array]") { console.log('value是數組'); }else if(Object.prototype.toString.call(value)==='[object Object]'){//這個方法兼容性好一點 console.log('value是對象'); }else{ console.log('value不是數組也不是對象') } } // 注意:千萬不能使用typeof來判斷對象和數組,由於這兩種類型都會返回"object"。
5.ES5的繼承和ES6的繼承有什麼區別?
ES5的繼承是經過prototype或構造函數機制來實現。
ES5的繼承實質上是先建立子類的實例對象,而後再將父類的方法添加到this上(Parement.apply(this))。
ES6的繼承機制實質上是先建立父類的實例對象this(因此必須先調用父類的super()方法),而後再用子類的構造函數修改this。具體爲ES6經過class關鍵字定義類,裏面有構造方法,類之間經過extends關鍵字實現繼承。子類必須在constructor方法中調用super方法,不然新建實例報錯。由於子類沒有本身的this對象,而是繼承了父類的this對象,而後對其調用。若是不調用super方法,子類得不到this對象。
注意:super關鍵字指代父類的實例,即父類的this對象。在子類構造函數中,調用super後,纔可以使用this關鍵字,不然報錯。
6.下面的ul,如何點擊每一列的時候alert其index?(閉包)
<ul id=」test」> <li>這是第一條</li> <li>這是第二條</li> <li>這是第三條</li> </ul> // 方法一: var lis=document.getElementById('test').getElementsByTagName('li'); for(var i=0;i<3;i++) { lis[i].index=i; lis[i].onclick=function(){ alert(this.index); }; } //方法二: var lis=document.getElementById('test').getElementsByTagName('li'); for(var i=0;i<3;i++) { lis[i].index=i; lis[i].onclick=(function(a){ return function() { alert(a); } })(i); }
7.對於MVVM的理解
MVVM 是 Model-View-ViewModel 的縮寫。
Model表明數據模型,也能夠在Model中定義數據修改和操做的業務邏輯。
View 表明UI 組件,它負責將數據模型轉化成UI 展示出來。
ViewModel 監聽模型數據的改變和控制視圖行爲、處理用戶交互,
簡單理解就是一個同步View 和 Model的對象,鏈接Model和View。
在MVVM架構下,View 和 Model 之間並無直接的聯繫,
而是經過ViewModel進行交互,Model 和 ViewModel 之間的交互是雙向的,
所以View 數據的變化會同步到Model中,而Model 數據的變化也會當即反應到View 上。
ViewModel 經過雙向數據綁定把 View 層和 Model 層鏈接了起來,
而View 和 Model 之間的同步工做徹底是自動的,無需人爲干涉,
所以開發者只需關注業務邏輯,不須要手動操做DOM,
不須要關注數據狀態的同步問題,
複雜的數據狀態維護徹底由 MVVM 來統一管理。
8.解釋Vue的生命週期
Vue實例從建立到銷燬的過程,就是生命週期。從開始建立、初始化數據、編譯模板、掛載Dom->渲染、更新->渲染、銷燬等一系列過程,稱之爲Vue的生命週期。
Vue的生命週期包括:
beforeCreate(建立前)在數據觀測和初始化事件還未開始,
created(建立後)完成數據觀測,屬性和方法的運算,初始化事件,$el屬性尚未顯示出來;
beforeMount(載入前)在掛載開始以前被調用,相關的render函數首次被調用,實例已完成如下的配置:編譯模板,把data裏面的數據和模板生成html,注意此時尚未掛載html到頁面上;
mounted(載入後)在el被新建立的vm.$el替換,並掛載到實例上去以後調用,實例已完成如下配置:用上面編譯好的html內容替換el屬性指向的DOM對象,完成模板中的html渲染到html頁面中,此過程當中進行ajax交互。
beforeUpdate(更新前)在數據更新以前調用,發生在虛擬DOM從新渲染和打補丁以前,能夠在該鉤子中進一步地更改狀態,不會觸發附加的重渲染過程。
updated(更新後)在因爲數據更改致使的虛擬DOM從新渲染和打補丁以後調用。調用時,組件DOM已經更新,因此能夠執行依賴於DOM的操做。然而在大多數狀況下,應該避免在此期間更改狀態,由於這可能會致使更新無限循環,該鉤子在服務器渲染期間不被調用。
beforeDestroy(銷燬前)在實例銷燬以前調用,實例仍然徹底可用。
destroyed(銷燬後)在實例銷燬以後調用。調用後,全部的事件監聽器會被移除,全部的子實例也會被銷燬。該鉤子在服務器端渲染期間不被調用。
9.爲何使用Node.js,它有哪些優缺點?
優勢:
事件驅動,經過閉包很容易實現客戶端的生命活期。
不用擔憂多線程,鎖,並行計算的問題
V8引擎速度很是快
對於遊戲來講,寫一遍遊戲邏輯代碼,前端後端通用
缺點:
nodejs更新很快,可能會出現版本兼容
nodejs還不算成熟,尚未大製做
nodejs不像其餘的服務器,對於不一樣的連接,不支持進程和線程操做
10.什麼是錯誤優先的回調函數?
錯誤優先(Error-first)的回調函數(Error-First Callback)用於同時返回錯誤和數據。
第一個參數返回錯誤,而且驗證它是否出錯;其餘參數返回數據。
fs.readFile(filePath, function(err, data) { if (err) { // 處理錯誤 return console.log(err); } console.log(data); });
11.使用npm有哪些好處?
經過npm,你能夠安裝和管理項目的依賴,
而且可以指明依賴項的具體版本號。
對於Node應用開發而言,
你能夠經過package.json文件來管理項目信息,
配置腳本,以及指明依賴的具體版本
12.在JavaScript源文件的開頭包含 use strict 有什麼意義和好處?
use strict 是一種在JavaScript代碼運行時自動實行更嚴格解析和錯誤處理的方法。(嚴格模式)
將值分配給一個未聲明的變量會自動建立該名稱的全局變量。這是JavaScript中最多見的錯誤之一。在嚴格模式下,這樣作的話會拋出錯誤。消除 this 強制。
當檢測到對象(例如,var object = {foo: "bar", foo: "baz"};)中重複命名的屬性,或檢測到函數中(例如,function foo(val1, val2, val1){})重複命名的參數時,嚴格模式會拋出錯誤,所以捕捉幾乎能夠確定是代碼中的bug能夠避免浪費大量的跟蹤時間。使eval() 更安全。
13.vuejs與angularjs以及react的區別?
與AngularJS的區別
相同點:
都支持指令:內置指令和自定義指令。
都支持過濾器:內置過濾器和自定義過濾器。
都支持雙向數據綁定。
都不支持低端瀏覽器。
不一樣點:
1.AngularJS的學習成本高,好比增長了Dependency Injection特性,而Vue.js自己提供的API都比較簡單、直觀。
2.在性能上,AngularJS依賴對數據作髒檢查,因此Watcher越多越慢。
Vue.js使用基於依賴追蹤的觀察而且使用異步隊列更新。全部的數據都是獨立觸發的。
對於龐大的應用來講,這個優化差別仍是比較明顯的。
與React的區別
相同點:
React採用特殊的JSX語法,Vue.js在組件開發中也推崇編寫.vue特殊文件格式,對文件內容都有一些約定,二者都須要編譯後使用。
中心思想相同:一切都是組件,組件實例之間能夠嵌套。
都提供合理的鉤子函數,可讓開發者定製化地去處理需求。
都不內置列數AJAX,Route等功能到核心包,而是以插件的方式加載。
在組件開發中都支持mixins的特性。
不一樣點:
React依賴Virtual DOM,而Vue.js使用的是DOM模板。React採用的Virtual DOM會對渲染出來的結果作髒檢查。
Vue.js在模板中提供了指令,過濾器等,能夠很是方便,快捷地操做Virtual DOM。
14.<keep-alive></keep-alive>的做用是什麼?
<keep-alive></keep-alive> 包裹動態組件時,會緩存不活動的組件實例,主要用於保留組件狀態或避免從新渲染。
15.WeakMap 和 Map 的區別?
WeakMap 結構與 Map 結構基本相似,惟一的區別是它只接受對象做爲鍵名( null 除外),不接受其餘類型的值做爲鍵名,並且鍵名所指向的對象,不計入垃圾回收機制。
WeakMap 最大的好處是能夠避免內存泄漏。一個僅被 WeakMap 做爲 key 而引用的對象,會被垃圾回收器回收掉。
WeakMap 擁有和 Map 相似的 set(key, value) 、get(key)、has(key)、delete(key) 和 clear() 方法, 沒有任何與迭代有關的屬性和方法。
16.http和https的基本概念?
http: 超文本傳輸協議,是互聯網上應用最爲普遍的一種網絡協議,是一個客戶端和服務器端請求和應答的標準(TCP),用於從WWW服務器傳輸超文本到本地瀏覽器的傳輸協議,它可使瀏覽器更加高效,使網絡傳輸減小。
https: 是以安全爲目標的HTTP通道,簡單講是HTTP的安全版,即HTTP下加入SSL層,HTTPS的安全基礎是SSL,所以加密的詳細內容就須要SSL。
https協議的主要做用是:創建一個信息安全通道,來確保數組的傳輸,確保網站的真實性。
17.git fetch和git pull的區別?
git pull:至關因而從遠程獲取最新版本並merge到本地
git fetch:至關因而從遠程獲取最新版本到本地,不會自動merge
18.介紹一下對瀏覽器內核的理解?
主要分紅兩部分:渲染引擎(layout engineer或Rendering Engine)和JS引擎。
渲染引擎:負責取得網頁的內容(HTML、XML、圖像等等)、
整理訊息(例如加入CSS等),以及計算網頁的顯示方式,而後會輸出至顯示器或打印機。
瀏覽器的內核的不一樣對於網頁的語法解釋會有不一樣,因此渲染的效果也不相同。
全部網頁瀏覽器、電子郵件客戶端以及其它須要編輯、顯示網絡內容的應用程序都須要內核。
JS引擎則:解析和執行javascript來實現網頁的動態效果。
最開始渲染引擎和JS引擎並無區分的很明確,後來JS引擎愈來愈獨立,內核就傾向於只指渲染引擎。
19.什麼是微格式
微格式(Microformats)是一種讓機器可讀的語義化XHTML詞彙的集合,是結構化數據的開放標準。
是爲特殊應用而制定的特殊格式
優勢:將智能數據添加到網頁上,讓網站內容在搜索引擎結果界面能夠顯示額外的提示。
20.數據綁定基本的實現
// 實現一個方法,能夠給 obj 全部的屬性添加動態綁定事件,當屬性值發生變化時會觸發事件 let obj = { key_1: 1, key_2: 2 } function func(key) { console.log(key + ' 的值發生改變:' + this[key]); } bindData(obj, func); obj.key_1 = 2; // 此時自動輸出 "key_1 的值發生改變:2" obj.key_2 = 1; // 此時自動輸出 "key_2 的值發生改變:1"
答案:
function bindData(obj, fn) { for (let key in obj) { Object.defineProperty(obj, key, { set(newVal) { if (this.value !== newVal) { this.value = newVal; fn.call(obj, key); } }, get() { return this.value; } }) } }
20.數據結構處理
// 有一個祖先樹狀 json 對象,當一我的有一個兒子的時候,其 child 爲其兒子對象,若是有多個兒子,child 爲兒子對象的數組。 請實現一個函數,找出這個家族中全部有多個兒子的人的名字(name),輸出一個數組。 列子: // 樣例數據 let data = { name: 'jack', child: [ { name: 'jack1' }, { name: 'jack2', child: [{ name: 'jack2-1', child: { name: 'jack2-1-1' } }, { name: 'jack2-2' }] }, { name: 'jack3', child: { name: 'jack3-1' } } ] } 答案: 用遞歸 function findMultiChildPerson(data) { let nameList = []; function tmp(data) { if (data.hasOwnProperty('child')) { if (Array.isArray(data.child)) { nameList.push(data.name); data.child.forEach(child => tmp(child)); } else { tmp(data.child); } } } tmp(data); return nameList; } 不用遞歸 function findMultiChildPerson(data) { let list = [data]; let nameList = []; while (list.length > 0) { const obj = list.shift(); if (obj.hasOwnProperty('child')) { if (Array.isArray(obj.child)) { nameList.push(obj.name); list = list.concat(obj.child); } else { list.push(obj.child); } } } return nameList; }