常用的四種設計模式
1.工廠模式:解決多個相似的問題;
2.單例模式:只能被實例化一次;
3.沙箱模式:自執行函數,使用閉包把內部方法暴露出來,例:
var fn=(function(){
function aFn(){};
return {
aFn:aFn
}
})
4.發佈者訂閱模式:有新消息主動推送的功能模式;
編程方式及其優缺點
1.命令式編程(流水式從上至下執行)
2.面向編程(函數式編程:閉包(函數組合嵌套的方式),一類函數,箭頭函數)
3.面向對象式編程(OOP:原型(鏈式的鏈接對象的對象)繼承(存在父子間屬性函數的使用))
優缺點: 對象函數屬性排列易於理解;命令式編碼風格計算機能直接快速編譯;
多實例時亂象叢生,容易修改原始值導致解析不理想化(缺點)
4.函數式編程:
優缺點: 避免面向對象編程的缺點,自我執行理想化程度高;
複用性良好,存在參數無參數狀態,且可以高效完成算法;
執行邏輯清晰,方便修改和優化更新;
避免多線程衝突,邏輯混亂
簡潔度很好,易讀性稍差(缺點)
JS語法的基本規範
不要在同一行聲明多個變量。
請使用 ===/!==來比較true/false或者數值
使用對象字面量替代new Array這種形式
不要使用全局函數。
Switch語句必須帶有default分支
函數不應該有時候有返回值,有時候沒有返回值。
for循環必須使用大括號
if語句必須使用大括號
for-in循環中的變量 應該使用var關鍵字明確限定作用域,從而避免作用域污染。
書寫高性能JS的方法
遵循嚴格模式:"use strict";
將js腳本放在頁面底部,加快渲染頁面
將js腳本將腳本成組打包,減少請求
使用非阻塞方式下載js腳本
儘量使用局部變量來保存全局變量
儘量減少使用閉包
使用 window 對象屬性方法時,省略 window
儘量減少對象成員嵌套
緩存 DOM 節點的訪問
通過避免使用 eval() 和 Function() 構造器
給 setTimeout() 和 setInterval() 傳遞函數而不是字符串作爲參數
儘量使用直接量創建對象和數組
最小化重繪(repaint)和迴流(reflow)
JS的組成
三部分組成:
ECMAScript(核心):JavaScript 語言基礎
DOM(文檔對象模型):規定了訪問HTML和XML的接口
BOM(瀏覽器對象模型):提供了瀏覽器窗口之間進行交互的對象和方法
JS有的內置對象(ES6新增對象請查看詳情)
數據封裝類對象:Object、Array、Boolean、Number、String
其他對象:Function、Arguments、Math、Date、RegExp、Error
ES6新增對象:Symbol、Map、Set、Promises、Proxy、Reflect
獲取本地時間的時間戳
var timestamp=Date.parse(new Date()); //特殊存在:毫秒顯示爲000(不取秒以下的數值)
var timestamp=(new Date()).valueOf();
var timestamp=new Date().getTime();
‘類繼承’和‘原型繼承’的區別
類繼承:
實例由類繼承而來(建築圖紙和實際建築的關係),同時還會創建父類—子類這樣一種關係,也叫做類的分層
分類。通常是用 new 關鍵字調用類的構造函數來創建實例的。不過在 ES6 中,要繼承 一個類,不用 class 關
鍵字也可以。儘量不用類繼承,除非是單一級的使用。
原型繼承:
實例/對象直接從其它對象繼承而來,創建實例的話,往往用工廠函數或者 Object.create() 方法。實例可
以從多個不同的對象組合而來,這樣就能選擇性地繼承了。主要實現手段有:委託(原型鏈);組合;函數式(這
個函數式原型繼承不是函數式編程。這裏的函數是用來創建一個閉包,以實現私有狀態或者封裝)
雙向數據綁定,單向數據流的含義和區別
雙向數據綁定:
UI 層所呈現的內容和 Model 層的數據動態地綁定在一起,其中一個發生了變化,就會立刻反映在另一個
上。比如用戶在前端頁面的表單控件中輸入了一個值,Model 層對應該控件的變量就會立刻更新爲用戶所輸入的
值;反之亦然,如果 Modal 層的數據有變化,變化後的數據也會立刻反映至 UI 層。Angular 則是雙向數據綁
定的典型。
單向數據流:
意味着只有 Model 層纔是單一數據源。UI 層的變化會觸發對應的消息機制,告知 Model 層用戶的目的。
只有 Model 層纔有更改應用狀態的權限,這樣一來,數據永遠都是單向流動的,其狀態的變化是很容易跟蹤的。
React 是單向數據流的典型。
基本類型與引用類型的區別
基本數據類型: Undefined、Null、Boolean、Number、String
引用數據類型: Object, Array, Date, RegExp(正則), Function
區別:
存儲:
基本類型值在內存中佔據固定大小的空間,因此被保存在棧內存中
引用類型的值是對象, 保存在堆內存中. 引用類型的變量實際上是一個指向該對象的指針
複製:
從一個變量向另一個變量複製基本類型的值, 會創建這個值的一個副本
從一個變量向另一個變量複製引用類型的值, 複製的其實是指針, 因此兩個變量最終都指向同一個對象
檢測:
確定一個值是哪種基本類型可以用typeof操作符
確定一個值是哪種引用類型可以使用instanceof操作符
null,undefined 的區別
undefined 表示不存在這個值 typeof undefined //"undefined"
null 一個對象被定義了,值爲“空值” typeof null //"object"
undefined :是一個表示"無"的原始值或者說表示"缺少值",就是此處應該有一個值,但是還沒有定義。例如變量
被聲明瞭,但沒有賦值時,就等於undefined
null :是一個空對象, 沒有任何屬性和方法。例如作爲函數的參數,表示該函數的參數不是對象
注意:在驗證null時,一定要使用 === ,因爲 == 無法分別 null 和 undefined
閉包(closure)的基本瞭解
閉包:是指有權訪問另一個函數作用域中變量的函數。
特點:
1.創建閉包的最常見的方式就是在一個函數內創建另一個函數;
2.利用閉包可以突破作用鏈域,將函數內部的變量和方法傳遞到外部;
3.使用閉包主要是爲了設計私有的方法和變量;
4.閉包的優點是可以避免全局變量的污染,缺點是閉包會常駐內存,會增大內存使用量;
5.在js中,函數即閉包,只有函數纔會產生作用域的概念;
特徵:
1.函數內再嵌套函數;
2.內部函數可以引用外層的參數和變量;
3.參數和變量不會被垃圾回收機制回收;
例子:
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
add();
//1
add();
//2
閉包的使用場景
1.代替全局變量
2.函數外或在其他函數中訪問某一函數內部的參數
3.在函數執行之前爲要執行的函數提供具體參數
4.在函數執行之前爲函數提供只有在函數執行或引用時才能知道的具體參數
5.爲節點循環綁定click事件,在事件函數中使用當次循環的值或節點,而不是最後一次循環的值或節點
6.暫停執行
7.包裝相關功能
僞數組的概念
僞數組概念:是能通過Array.prototype.slice 轉換爲真正的數組的帶有length屬性的對象;
僞數組示例:
1.arguments對象
2.調用getElementsByTagName,document.childNodes之類的node集合
僞數組變更:
Array.prototype.slice.call(fakeArray)轉變爲真正的Array對象,返回新數組而不會修改原數組
辨別數組的方式
1.obj instanceof Array 如果返回 true;
2.Object.prototype.toString.call(obj) === "[object Array]";
3.obj.constructor == Array爲 true;
4.ES6的Array.isArray(obj)返回 true;
javascript創建對象的方式
1.對象字面量(最後一個key-value不添加逗號)
var obj={
name:"yjs",
age:25,
};
優缺點:複用性較差(缺)
2.構造函數(函數名首字母使用大寫,區分函數和自定義對象,可以傳參的呦)
function NewObj(){}
var person=new NewObj();
person.name="yjs";
person.age="25";
person.city="sjz";
person.getName=function(){
console.log("對象的名稱是:"+person.name)
}
person.getName();
優缺點:複用性較差(缺)
3.構造函數-含參(用this關鍵字定義構造的上下文屬性,一般不會出現return的語句)
function One(name,age,city){
this.name=name;
this.age=age;
this.city=city;
this.getName=function(){
console.log("對象的名稱是:"+person.name)
}
}
var one=new One("yjs",25,"sjz");//實例化對象
one.getName();
優缺點:實例化的對象可以識別指定的類型(優);每次實例都會重新創建函數,全局變量多(缺)
4.工廠函數(內置對象,這種事最不推薦使用的)
var per=new Object();
per.name="yjs";
per.age=25;
per.city="sjz";
per.getName=function(){
console.log("對象的名稱是:"+person.name)
}
per.getName();
優缺點:所有的實例都指向一個原型,對象無法識別(缺)
5.原型
function One(){}
One.prototype.name="yjs";
One.prototype.getName=function(){
console.log("對象的名稱是:"+person.name)
}
var one=new One();
one.getName();
優缺點:創建函數放在原型避免全局變量多的問題(優);不能初始化參數(缺)
6.混合(舉例爲:構造函數方式和原型方式的混合,以上幾種可任意組合)
function One(name){
this.name=name;
}
One.prototype.getName=function(){
console.log("對象的名稱是:"+person.name)
}
var one=new One("yjs");
one.getName();
This對象的理解
1.this總是指向函數的直接調用者(而非間接調用者);
2.如果有new關鍵字,this指向new出來的那個對象;
3.事件中,this指向觸發這個事件的對象(特殊:IE中的attachEvent中的this總是指向全局對象Window);
call()和apply()方法實現繼承的區別
作用:都能繼承另一個對象的方法和屬性
區別:參數列表不一樣
書寫:Function.call(obj, arg1, arg2,...) Function.apply(obj, args)
參數:obj-要被繼承的對象;第二個參數-傳遞的實參值
舉例:
function A(a){console.log(a)}
function B(b,c){console.log(b+c)}
A.call(B,10); //10
B.applay(A,[10,20]) //30
new操作符的原理
1.創建一個空對象,並且 this 變量引用該對象,同時還繼承了該函數的原型。
var obj = {};
2.屬性和方法被加入到 this 引用的對象中。
obj.__proto__ = Base.prototype;
3.新創建的對象由 this 所引用,並且最後隱式的返回 this 。
Base.call(obj);
IE與火狐的事件機制有什麼區別? 如何阻止冒泡
事件:網頁中的某個操作,點擊,懸停,雙擊,鍵盤事件等
機制:IE是事件冒泡、其他的瀏覽器同時支持兩種事件模型(捕獲型事件和冒泡型事件)
阻止:ev.stopPropagation();(舊ie的方法 ev.cancelBubble = true;)
事件委託(事件代理)
原理:事件冒泡, 委託到已知的父級元素。
範圍:1.js腳本動態添加的;2.不好定位的元素事件;3.相同元素過多;
例子:
html部分:
<ul id="list">
<li id="li-1">Li 2</li>
<li id="li-2">Li 3</li>
</ul>
js部分:
document.getElementById("list").addHandler("click", function(e){
var e = e || window.event;
var target = e.target || e.srcElement;
if(target.nodeName.toUpperCase == "LI"){
console.log("li的ID是:"+e,target.id);
}
});
XML和JSON的區別
1.JSON相對於XML來講,數據的體積小,傳遞的速度更快;
2.JSON與JavaScript的交互更加方便,更容易解析處理,更好的數據交互;
3.JSON對數據的描述性比XML較差;
4.JSON的速度要遠遠快於XML;
哪些操作會造成內存泄漏
1.setTimeout 的第一個參數使用字符串而非函數的話,會引發內存泄漏;
2.閉包、控制檯日誌、循環(在兩個對象彼此引用且彼此保留時,就會產生一個循環);
3.當頁面中元素被移除或替換時,若元素綁定的事件仍沒被移除,在IE中不會作出恰當處理,此時要先手工移除事件,不然會存在內存泄露。
面向對象中繼承實現
1.prototype原型鏈方式:
function One(name){
this.name = name;
this.getName=function(){
console.log(this.name);
}
}
function Two(name){
this.name = name;
}
Two.prototype = new One();
var a = new One("gc");
var b = new Two("yjs");
a.getName(); //gc
b.getName(); //yjs
2、call()/apply()方法
function One(name){
this.name = name;
this.getName=function(){
console.log(this.name);
}
}
function Two(){
var args = arguments;
One.call(this,args[0]); // One.apply(this,arguments);
}
var a = new One("gc");
var b = new Two("yjs");
a.getName(); //gc
b.getName(); //yjs
3.混合方法(prototype,call/apply)
function One(name){
this.name = name;
this.getName=function(){
console.log(this.name);
}
}
function Two(){
var args = arguments;
One.call(this,args[0]);
}
Two.prototype = new One();
var b = new Two("yjs");
b.getName(); //yjs
4.對象冒充
function One(name){
this.name = name;
this.getName=function(){
console.log(this.name);
}
}
function Two(name){
this.tt = One; //將One類的構造函數賦值給this.tt
this.tt(name); //js中實際上是通過對象冒充來實現繼承的
delete this.tt; //移除對One的引用
}
var a = new One("gc");
var b = new Two("yjs");
a.getName(); //gc
b.getName(); //yjs
sessionStorage 、localStorage 和 cookie 的區別
共同點:用於瀏覽器端存儲的緩存數據
不同點:
1.存儲內容是否發送到服務器端:當設置了Cookie後,數據會發送到服務器端,造成一定的寬帶浪費;
web storage會將數據保存到本地,不會造成寬帶浪費;
2.數據存儲大小不同:Cookie數據不能超過4K,適用於會話標識;web storage數據存儲可以達到5M;
3.數據存儲的有效期限不同:cookie只在設置了Cookid過期時間之前一直有效,即使關閉窗口或者瀏覽器;
sessionStorage,僅在關閉瀏覽器之前有效;localStorage,數據存儲永久有效;
4.作用域不同:cookie和localStorage是在同源同窗口中都是共享的;sessionStorage不在不同的瀏覽器
窗口中共享,即使是同一個頁面;
Ajax的優缺點及工作原理
定義:AJAX(異步的 JavaScript 和 XML)。Ajax 是一種用於創建快速動態網頁的技術。
作用:Ajax 是一種在無需重新加載整個網頁的情況下,能夠更新部分網頁的技術。
優點:
1.減輕服務器的負擔;
2.減少用戶等待時間;
3.頁面和數據的分離;
缺點:
1.考慮瀏覽器兼容性;
2.頁面後退按鈕沒用;
3.支持的設備不廣泛;
原理:
1.創建ajax對象(XMLHttpRequest/ActiveXObject(Microsoft.XMLHttp))
2.判斷數據傳輸方式(GET/POST)
3.打開鏈接 open()
4.發送 send()
5.onreadystatechange 數據接收完成,判斷響應狀態 status 執行回調函數
代碼:
function loadXMLDoc(){
var xmlhttp;
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}else{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
//回調語句
}
}
xmlhttp.open("GET","/try/ajax/ajax_info.txt",true);
xmlhttp.send();
}
瀏覽器的渲染過程,DOM樹和渲染樹的區別
瀏覽器的渲染過程:
解析HTML構建 DOM(DOM樹),並行請求 css/image/js
CSS 文件下載完成,開始構建 CSSOM(CSS樹)
CSSOM 構建結束後,和 DOM 一起生成 Render Tree(渲染樹)
佈局(Layout):計算出每個節點在屏幕中的位置
顯示(Painting):通過顯卡把頁面畫到屏幕上
DOM樹 和 渲染樹 的區別:
DOM樹與HTML標籤一一對應,包括head和隱藏元素
渲染樹不包括head和隱藏元素,大段文本的每一個行都是獨立節點,每一個節點都有對應的css屬性
原型,原型鏈的基本概念
原型:
JavaScript的所有對象中都包含了一個 [__proto__] 內部屬性,這個屬性所對應的就是該對象的原型
JavaScript的函數對象,除了原型 [__proto__] 之外,還預置了 prototype 屬性
當函數對象作爲構造函數創建實例時,該 prototype 屬性值將被作爲實例對象的原型 [__proto__]。
原型鏈:
當一個對象調用的屬性/方法自身不存在時,就會去自己 [__proto__] 關聯的前輩 prototype 對象上去找
如果沒找到,就會去該 prototype 原型 [__proto__] 關聯的前輩 prototype 去找。依次類推,直到找
到屬性/方法或 undefined 爲止。從而形成了所謂的“原型鏈”
原型特點:
JavaScript對象是通過引用來傳遞的,當修改原型時,與之相關的對象也會繼承這一改變
Window 對象,Document 對象
Window:
Window 對象表示當前瀏覽器的窗口,是JavaScript的頂級對象。
Document:
Document 對象是 HTML 文檔的根節點與所有其他節點(元素節點,文本節點,屬性節點, 註釋節點)。
Window 對象的成員包括我們創建的所有對象、函數、變量,Window 對象的方法和屬性是在全局範圍內有效的。
Document 對象使我們可以通過腳本對 HTML 頁面中的所有元素進行訪問,是 Window 對象的一部分。
IE的事件處理和W3C的事件處理的區別
綁定事件:
W3C: targetEl.addEventListener('click', handler, false);
IE: targetEl.attachEvent('onclick', handler);
刪除事件:
W3C: targetEl.removeEventListener('click', handler, false);
IE: targetEl.detachEvent(event, handler);
事件對象:
W3C: var e = arguments.callee.caller.arguments[0]
IE: window.event
事件目標:
W3C: e.target
IE: window.event.srcElement
阻止事件默認行爲:
W3C: e.preventDefault()
IE: window.event.returnValue = false
阻止冒泡:
W3C: e.stopPropagation()
IE: window.event.cancelBubble = true
js延遲加載的方式
defer和async:defer同步加載js文件,async異步加載js文件。
動態創建DOM方式(用得最多):document.createElement('script')。
按需異步載入js
DOM操作——添加、移除、移動、複製、創建,查找節點
1、獲取節點
document.getElementById(idName) //返回一個元素對象
document.getElementsByName(name) //返回元素對象僞數組
document.getElementsByClassName(className) //返回元素對象僞數組
document.getElementsByTagName(tagName) //返回元素對象僞數組
2、獲取/設置屬性
element.getAttribute(attributeName) //返回對應屬性的屬性值
element.setAttribute(attributeName,attributeValue) //傳入屬性名及設置的值
3、創建節點
document.createElement("h3") //創建一個html元素
document.createTextNode(String); //創建一個文本節點
document.createAttribute("class"); //創建一個屬性節點
4、增添節點
element.appendChild(Node); //往element內部最後面添加一個節點
elelment.insertBefore(newNode,existingNode); //在element內部的中在existingNode前面插入
5、刪除節點
element.removeChild(Node) //刪除當前節點下
JavaScript 中,調用函數的方式
方法調用模式 Foo.foo(arg1, arg2);
函數調用模式 foo(arg1, arg2);
構造器調用模式 (new Foo())(arg1, arg2);
call/applay調用模式 Foo.foo.call(that, arg1, arg2);
bind調用模式 Foo.foo.bind(that)(arg1, arg2)();