三者均可以把一個函數應用到其餘對象上,apply
,call
是直接執行函數調用,bind
是綁定,執行須要再次調用。 apply
和call
的區別是apply
接受數組做爲參數,而call
是接受逗號分隔的無限多個參數列表。
代碼以下:javascript
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須要先綁定,再執行
Object.defineProperty(obj,prop,descriptor)
用來給對象定義屬性,有value
,writeable
,enumerable
,set/get
,configurable
,hasOwnProperty
用於檢查某一屬性是否是存在於對象自己, propertyIsEnumerable
用來檢測某一屬性是否可遍歷,也就是能不能用for...in
循環來取到。html
// 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'); // 發佈一個字符串到全部訂閱者
charAt() // 返回在指定位置的字符。 concat() // 鏈接字符串。 fromCharCode() // 從字符編碼建立一個字符串。 indexOf() // 檢索字符串。 match() // 找到一個或多個正則表達式的匹配。 replace() // 替換與正則表達式匹配的子串。 search() // 檢索與正則表達式相匹配的值。 slice() // 提取字符串的片段,並在新的字符串中返回被提取的部分。 split() // 把字符串分割爲字符串數組。 substr() // 從起始索引號提取字符串中指定數目的字符。 substring() // 提取字符串中兩個指定的索引號之間的字符。 toLocaleLowerCase() // 把字符串轉換爲小寫。 toLocaleUpperCase() // 把字符串轉換爲大寫。 toLowerCase() // 把字符串轉換爲小寫。 toUpperCase() // 把字符串轉換爲大寫。 toString() // 返回字符串。 valueOf() // 返回某個字符串對象的原始值。
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"。
ES5
的繼承是經過prototype
或構造函數機制來實現。ES5
的繼承實質上是先建立子類的實例對象,而後再將父類的方法添加到this
上(Parent.apply(this)
)。ES6
的繼承機制實質上是先建立父類的實例對象this
(因此必須先調用父類的super()
方法),而後再用子類的構造函數修改this
。具體爲ES6
經過class
關鍵字定義類,裏面有構造方法,類之間經過extends
關鍵字實現繼承。子類必須在constructor
方法中調用super
方法,不然新建實例報錯。由於子類沒有本身的this
對象,而是繼承了父類的this
對象,而後對其調用。若是不調用super
方法,子類得不到this
對象。前端
注意:super關鍵字指代父類的實例,即父類的this對象。在子類構造函數中,調用super後,纔可以使用this關鍵字,不然報錯。
<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); }
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
來統一管理。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
(銷燬後)在實例銷燬以後調用。調用後,全部的事件監聽器會被移除,全部的子實例也會被銷燬。該鉤子在服務器端渲染期間不被調用。java
優勢:
事件驅動,經過閉包很容易實現客戶端的生命活期。
不用擔憂多線程,鎖,並行計算的問題V8
引擎速度很是快
對於遊戲來講,寫一遍遊戲邏輯代碼,前端後端通用
缺點:node.js
更新很快,可能會出現版本兼容node.js
還不算成熟,尚未大製做node.js
不像其餘的服務器,對於不一樣的連接,不支持進程和線程操做node
錯誤優先(Error-first
)的回調函數(Error-First Callback
)用於同時返回錯誤和數據。
第一個參數返回錯誤,而且驗證它是否出錯;其餘參數返回數據。react
fs.readFile(filePath, function(err, data) { if (err) { // 處理錯誤 return console.log(err); } console.log(data); });
經過npm
,你能夠安裝和管理項目的依賴,
而且可以指明依賴項的具體版本號。
對於Node
應用開發而言,
能夠經過package.json
文件來管理項目信息,
配置腳本,以及指明依賴的具體版本。git
use strict
是一種在JavaScript
代碼運行時自動實行更嚴格解析和錯誤處理的方法。(嚴格模式)
將值分配給一個未聲明的變量會自動建立該名稱的全局變量。這是JavaScript
中最多見的錯誤之一。在嚴格模式下,這樣作的話會拋出錯誤。消除 this
強制。
當檢測到對象(例如,var object = {foo: "bar", foo: "baz"};
)中重複命名的屬性,或檢測到函數中(例如,function foo(val1, val2, val1){}
)重複命名的參數時,嚴格模式會拋出錯誤,所以捕捉幾乎能夠確定是代碼中的bug
能夠避免浪費大量的跟蹤時間。比eval()
更安全。angularjs
與AngularJS
的區別
相同點:
都支持指令:內置指令和自定義指令。
都支持過濾器:內置過濾器和自定義過濾器。
都支持雙向數據綁定。
都不支持低端瀏覽器。
不一樣點:
1.AngularJS
的學習成本高,好比增長了Dependency Injection
特性,而Vue.js
自己提供的API
都比較簡單、直觀。
2.在性能上,AngularJS
依賴對數據作髒檢查,因此Watcher
越多越慢。Vue.js
使用基於依賴追蹤的觀察而且使用異步隊列更新。全部的數據都是獨立觸發的。
對於龐大的應用來講,這個優化差別仍是比較明顯的。ajax
與React
的區別
相同點:React
採用特殊的JSX
語法,Vue.js
在組件開發中也推崇編寫.vue
特殊文件格式,對文件內容都有一些約定,二者都須要編譯後使用。
中心思想相同:一切都是組件,組件實例之間能夠嵌套。
都提供合理的鉤子函數,可讓開發者定製化地去處理需求。
都不內置列數AJAX
,Route
等功能到核心包,而是以插件的方式加載。
在組件開發中都支持mixins
的特性。
不一樣點:React
依賴Virtual DOM
,而Vue.js
使用的是DOM
模板。React
採用的Virtual DOM
會對渲染出來的結果作髒檢查。Vue.js
在模板中提供了指令,過濾器等,能夠很是方便,快捷地操做Virtual DOM
。
<keep-alive></keep-alive>
包裹動態組件時,會緩存不活動的組件實例,主要用於保留組件狀態或避免從新渲染。
WeakMap
結構與 Map
結構基本相似,惟一的區別是它只接受對象做爲鍵名( null
除外),不接受其餘類型的值做爲鍵名,並且鍵名所指向的對象,不計入垃圾回收機制。WeakMap
最大的好處是能夠避免內存泄漏。一個僅被 WeakMap
做爲 key
而引用的對象,會被垃圾回收器回收掉。WeakMap
擁有和 Map
相似的 set(key, value)
、get(key)
、has(key)
、delete(key)
和 clear()
方法, 沒有任何與迭代有關的屬性和方法。
http
: 超文本傳輸協議,是互聯網上應用最爲普遍的一種網絡協議,是一個客戶端和服務器端請求和應答的標準(TCP
),用於從WWW
服務器傳輸超文本到本地瀏覽器的傳輸協議,它可使瀏覽器更加高效,使網絡傳輸減小。https
: 是以安全爲目標的HTTP
通道,簡單講是HTTP
的安全版,即HTTP
下加入SSL
層,HTTPS
的安全基礎是SSL
,所以加密的詳細內容就須要SSL
。https
協議的主要做用是:創建一個信息安全通道,來確保數組的傳輸,確保網站的真實性。
git pull
:至關因而從遠程獲取最新版本並merge
到本地git fetch
:至關因而從遠程獲取最新版本到本地,不會自動merge
主要分紅兩部分:渲染引擎(layout engineer
或Rendering Engine
)和JS
引擎。
渲染引擎:負責取得網頁的內容(HTML
、XML
、圖像等等)、
整理訊息(例如加入CSS
等),以及計算網頁的顯示方式,而後會輸出至顯示器或打印機。
瀏覽器的內核的不一樣對於網頁的語法解釋會有不一樣,因此渲染的效果也不相同。
全部網頁瀏覽器、電子郵件客戶端以及其它須要編輯、顯示網絡內容的應用程序都須要內核。JS
引擎:解析和執行javascript
來實現網頁的動態效果。
最開始渲染引擎和JS
引擎並無區分的很明確,後來JS
引擎愈來愈獨立,內核就傾向於只指渲染引擎。
微格式(Microformats
)是一種讓機器可讀的語義化XHTML
詞彙的集合,是結構化數據的開放標準。
是爲特殊應用而制定的特殊格式
優勢:將智能數據添加到網頁上,讓網站內容在搜索引擎結果界面能夠顯示額外的提示。
// 實現一個方法,能夠給 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; } }) } }
// 有一個祖先樹狀 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; }