總結篇-Javascript部分(絕對乾貨,未完待續...)
阿新 • • 發佈:2018-12-12
0-0.常用的四種設計模式
1.工廠模式:解決多個相似的問題;
2.單例模式:只能被例項化一次;
3.沙箱模式:自執行函式,使用閉包把內部方法暴露出來,例:
var fn=(function(){
function aFn(){};
return {
aFn:aFn
}
})
4.釋出者訂閱模式:有新訊息主動推送的功能模式;
0-1.程式設計正規化
1.指令式程式設計(流水式從上至下執行) 2.面向程式設計(函數語言程式設計:閉包(函式組合巢狀的方式),一類函式,箭頭函式) 3.面向物件式程式設計(OOP:原型(鏈式的連結物件的物件)繼承(存在父子間屬性函式的使用)) 優缺點: 物件函式屬性排列易於理解;命令式編碼風格計算機能直接快速編譯; 多例項時亂象叢生,容易修改原始值導致解析不理想化(缺點) 4.函數語言程式設計: 優缺點: 避免面向物件程式設計的缺點,自我執行理想化程度高; 複用性良好,存在引數無引數狀態,且可以高效完成演算法; 執行邏輯清晰,方便修改和優化更新; 避免多執行緒衝突,邏輯混亂 簡潔度很好,易讀性稍差(缺點)
0-2.寫JavaScript的基本規範?
不要在同一行宣告多個變數。
請使用 ===/!==來比較true/false或者數值
使用物件字面量替代new Array這種形式
不要使用全域性函式。
Switch語句必須帶有default分支
函式不應該有時候有返回值,有時候沒有返回值。
for迴圈必須使用大括號
if語句必須使用大括號
for-in迴圈中的變數 應該使用var關鍵字明確限定作用域,從而避免作用域汙染。
1.模擬字串去的hash值
function hashCode(str){ var h = 0, off = 0; var len = str.length; for(var i = 0; i < len; i++){ h = 31 * h + str.charCodeAt(off++); } var t=-2147483648*2; if(h>2147483647){ h+=t } return h; }
2.獲取本地時間的時間戳
var timestamp=Date.parse(new Date()); //特殊存在:毫秒顯示為000(不去秒以下的數值)
var timestamp=(new Date()).valueOf();
var timestamp=new Date().getTime();
3.fixed固定定位不隨滾動條移動
<div class=”fixedDiv”>…</div> .fixedDiv{ position:fixed; width:1000px; bottom:0; z-index:1000; } window.onscroll=function(){ var sl=Math.max(document.body.scrollLeft,document.documentElement.scrollLeft); document.getElementsByClassName(“fixedDiv”)[0].style.left=(-sl)+”px”; }
4.獲取指定字串中某字元出現的所有下標
function getAllIndex(str,chars){
var arr=[];
for(var i=0;i<str.length;i++){
if(str.substring(i,i+1)==chars){
arr.push(i)
}
}
return arr
}
5.監聽滾動條的事件,並獲取top&bottom的距離
$(window).scroll(function() {
var scrollTop = $(this).scrollTop();
var docHeight = $(document).height();
var windowHeight = $(this).height();
var scrollHeight=document.body.scrollHeight;
console.log("scrollTop:"+scrollTop);
console.log("scrollbottom:"+(docHeight-scrollTop-windowHeight));
if(scrollTop + windowHeight == docHeight) {
alert("已經到最底部了!");
}
});
6.-‘類繼承’和‘原型繼承’有什麼區別?
類繼承:
例項由類繼承而來(建築圖紙和實際建築的關係),同時還會建立父類—子類這樣一種關係,也叫做類的分層
分類。通常是用 new 關鍵字呼叫類的建構函式來建立例項的。不過在 ES6 中,要繼承 一個類,不用 class 關
鍵字也可以。儘量不用類繼承,除非是單一級的使用。
原型繼承:
例項/物件直接從其它物件繼承而來,建立例項的話,往往用工廠函式或者 Object.create() 方法。例項可
以從多個不同的物件組合而來,這樣就能選擇性地繼承了。主要實現手段有:委託(原型鏈);組合;函式式(這
個函式式原型繼承不是函數語言程式設計。這裡的函式是用來建立一個閉包,以實現私有狀態或者封裝)
7.雙向資料繫結/單向資料流的含義和區別
雙向資料繫結:
UI 層所呈現的內容和 Model 層的資料動態地繫結在一起,其中一個發生了變化,就會立刻反映在另一個
上。比如使用者在前端頁面的表單控制元件中輸入了一個值,Model 層對應該控制元件的變數就會立刻更新為使用者所輸入的
值;反之亦然,如果 Modal 層的資料有變化,變化後的資料也會立刻反映至 UI 層。Angular 則是雙向資料綁
定的典型。
單向資料流:
意味著只有 Model 層才是單一資料來源。UI 層的變化會觸發對應的訊息機制,告知 Model 層使用者的目的。
只有 Model 層才有更改應用狀態的許可權,這樣一來,資料永遠都是單向流動的,其狀態的變化是很容易跟蹤的。
React 是單向資料流的典型。
8.jquery不常用但實用的方法
(1)位置相關
offset() $(“#qq”).offset() 相對瀏覽器視窗的位置
offsetParent() $(“#qq”).offsetParent() #qq相對最近的已經定位的祖先的位置
position() $(“#qq”).position() 已定位的元素的position值
(2)DOM元素的包裹
wrap() $(“#qq”).wrap(“<div id=’qqPar’/>”)
wrapAll() 所有指定元素都會被包裹
wrapInner() 指定元素的內容會被包裹
(3)刪除相關
detach() 刪除了還能恢復
empty() 刪除子元素的所有東西
remove() 刪除指定元素
unwrap() 刪除指定元素的父節點,但是保留本身
9.基本型別與引用型別有什麼區別?
基本資料型別: Undefined、Null、Boolean、Number、String
引用資料型別: Object, Array, Date, RegExp(正則), Function
區別:
儲存:
基本型別值在記憶體中佔據固定大小的空間,因此被儲存在棧記憶體中
引用型別的值是物件, 儲存在堆記憶體中. 引用型別的變數實際上是一個指向該物件的指標
複製:
從一個變數向另一個變數複製基本型別的值, 會建立這個值的一個副本
從一個變數向另一個變數複製引用型別的值, 複製的其實是指標, 因此兩個變數最終都指向同一個物件
檢測:
確定一個值是哪種基本型別可以用typeof操作符
確定一個值是哪種引用型別可以使用instanceof操作符
10.null,undefined 的區別?
undefined 表示不存在這個值 typeof undefined //"undefined"
null 一個物件被定義了,值為“空值” typeof null //"object"
undefined :是一個表示"無"的原始值或者說表示"缺少值",就是此處應該有一個值,但是還沒有定義。例如變數
被聲明瞭,但沒有賦值時,就等於undefined
null :是一個空物件, 沒有任何屬性和方法。例如作為函式的引數,表示該函式的引數不是物件
注意:在驗證null時,一定要使用 === ,因為 == 無法分別 null 和 undefined
11.什麼是閉包(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
12.什麼是偽陣列
偽陣列概念:是能通過Array.prototype.slice 轉換為真正的陣列的帶有length屬性的物件;
偽陣列示例:
1.arguments物件
2.呼叫getElementsByTagName,document.childNodes之類的node集合
偽陣列變更:
Array.prototype.slice.call(fakeArray)轉變為真正的Array物件,返回新陣列而不會修改原陣列
13.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();
14.談談This物件的理解。
1.this總是指向函式的直接呼叫者(而非間接呼叫者);
2.如果有new關鍵字,this指向new出來的那個物件;
3.事件中,this指向觸發這個事件的物件(特殊:IE中的attachEvent中的this總是指向全域性物件Window);
15.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
16.new操作符具體幹了什麼
1.建立一個空物件,並且 this 變數引用該物件,同時還繼承了該函式的原型。
var obj = {};
2.屬性和方法被加入到 this 引用的物件中。
obj.__proto__ = Base.prototype;
3.新建立的物件由 this 所引用,並且最後隱式的返回 this 。
Base.call(obj);
17.IE與火狐的事件機制有什麼區別? 如何阻止冒泡
事件:網頁中的某個操作,點選,懸停,雙擊,鍵盤事件等
機制:IE是事件冒泡、其他的瀏覽器同時支援兩種事件模型(捕獲型事件和冒泡型事件)
阻止:ev.stopPropagation();(舊ie的方法 ev.cancelBubble = true;)
18.事件委託(事件代理)是什麼
原理:事件冒泡, 委託到已知的父級元素。
範圍: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);
}
});
19.XML和JSON的區別
1.JSON相對於XML來講,資料的體積小,傳遞的速度更快;
2.JSON與JavaScript的互動更加方便,更容易解析處理,更好的資料互動;
3.JSON對資料的描述性比XML較差;
4.JSON的速度要遠遠快於XML;
20.哪些操作會造成記憶體洩漏
1.setTimeout 的第一個引數使用字串而非函式的話,會引發記憶體洩漏;
2.閉包、控制檯日誌、迴圈(在兩個物件彼此引用且彼此保留時,就會產生一個迴圈);
3.當頁面中元素被移除或替換時,若元素繫結的事件仍沒被移除,在IE中不會作出恰當處理,此時要先手工移除事件,不然會存在記憶體洩露。
21.面向物件中繼承實現
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
22.