JavaScript進階程式設計 學習筆記 js進階技巧

來源:互聯網
上載者:User

第十八章 進階技巧
1.進階函數
1.1 範圍安全的建構函式
①直接調用建構函式而不適用new操作符時,由於this對象的晚綁定,它將映射在全域對象window上,導致對象屬性錯誤增加到window。 複製代碼 代碼如下:function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
}
Var person = Person("Jay",29,"singer"); //屬性增加到window對象上。

②範圍安全建構函式 複製代碼 代碼如下:function Person(name,age,job){
if(this instanceof Person){
this.name = name;
this.age = age;
}else{
return new Person(name,age);
}
}

③上述範圍安全的建構函式,如果使用建構函式竊模數式的繼承且不使用原型鏈,那麼這個繼承很可能被破壞。
□如果建構函式竊取結合使用原型鏈或者寄生式組合則可以解決這個問題。 複製代碼 代碼如下:function Polygon(side){
if(this instanceof Polygon){
this.sides = sides;
this.getArea = function{return 0;};
}else{
return new Polygon(sides);
}
}
function Rectangle(width,height){
Polygon.call(this,2);
this.width = width;
this.height = height;
this.getArea = function(){
return this.width * this.height;
};
}
Rectangle.prototype = new Polygon();
var rect = new Rectangle(5,10);
alert(rect.sides); //2

1.2 惰性載入函數
①惰性載入表示函數執行的分支僅會發生一次:既第一次調用的時候。在第一次調用的過程中,該函數會被覆蓋為另一個按合適方式執行的函數,這樣任何對原函數的調用都不用再經過執行的分支了。
■優點:
□要執行的適當代碼只有當實際調用函數時才進行。
□儘管第一次調用該函數會因額外的第二個函數調用而稍微慢點,但後續的調用都會很快,因避免了多重條件。 複製代碼 代碼如下:function create XHR(){
if(typeof XMLHttp Request != "undefined"){
createXHR = function(){
return new XMLHttpRequest();
};
}else if(typeof ActiveXObject != "undefined"){
createXHR = function(){
if(typeof arguments.callee.activeXString != "string"){
var versions = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"];
for(vai I = 0, len = versions.length; I < len; i++){
try{
Var xhr = new ActiveXObject(version[i]);
Arguments.callee.activeXString = version[i];
Return xhr;
}catch(ex){
//skip
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
};
}else{
createXHR = function(){
throw new Error("No XHR Object available.");
};
}
return createXHR();
}

1.3 函數綁定
①函數綁定要建立一個函數,可以在特定環境中以指定參數調用另一個函數。
②一個簡單的bind()函數接受一個函數和一個環境,並返回一個在給定環境中調用給定函數的函數,並且將所有參數原封不動傳遞過去。 複製代碼 代碼如下:function bind(fn, context){
return function(){
return fn.apply(context, arguments);
};
}

③被綁定函數與普通函數相比有更多的開銷——它們需要更多記憶體,同時也因為多重函數調用而稍微慢一點——所以最好只在必要時使用。
1.4 函數柯裡化
定義:用於建立已經設定好了一個或多個參數的函數。函數柯裡化的基本方法和函數綁定是一樣的:使用一個閉包返回一個函數。兩者的區別在於,當函數被調用時,返回函數還需要設定一些傳入的參數。 複製代碼 代碼如下:function bind(fn, context){
var args = Array.prototype.slice.call(arguments, 2);
return function(){
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return fn.apply(context,finalArgs);
};
}

2.進階定時器
①JavaScript是單線程程式,定時器是在間隔時間後將代碼添加到列隊。
②執行完一套代碼後,JavaScript進程返回一段很短的時間,這樣頁面上的其他處理就可以進行了。
2.1 重複的定時器
①setInterval()僅當沒有該定時器的任何其他代碼執行個體時,才將定時器代碼添加到隊列中。
□某些間隔會被跳過。
□多個定時器代碼執行之間的間隔可能會比預期小。
②避免setInterval()的兩個缺點,使用鏈式setTimeout()調用: 複製代碼 代碼如下:setTimeout(function(){
//處理
if(condition){
setTimeout(arguments.callee, interval);
}
},interval);

2.2 Yielding Processes
①JavaScript長時間運行指令碼制約:如代碼運行超過特定的時間或特定的語句數量就不會讓它繼續執行。
②當某個函數要花200ms以上的事件完成,最好分割為一系列可以使用定時器的小任務。
③數組分塊技術:為要處理的項目建立一個隊列,然後使用定時器取出下一個要處理的項目進行處理,接著再設定另一個定時器。 複製代碼 代碼如下:function chunk(array, process, context){
setTimeout(function(){
var item = array.shift();
process.call(context,item);
if(array.length>0){
setTimeout(arguments.callee, 100);
}
}
}

2.3 函數節流
①DOM操作比起非DOM互動需要更多記憶體和CPU時間。連續嘗試進行過多的DOM相關操作可能會導致瀏覽器掛起,有時甚至崩潰。
②函數節流思想:某些代碼不可以在沒有間斷的情況連續重複執行。
□樣本 複製代碼 代碼如下:var processor = {
timeoutId : null,
//實際進行處理的方法
performProcessing : function(){
//實際執行的方法
},
//初始處理調用的方法
process : function(){
clearTimeout(this.timeoutId);
var that = this;
this.timeoutId = setTimeout(function(){
that.performProcessing();
},100);
}
};
//嘗試開始執行
Processor.process();
□簡化模式
function throttle(method,context){
clearTimeout(mehtod.tId);
mehtod.tId = setTimeout(function(){
method.call(context);
},100);
}

3.自訂事件
①事件是一種叫做觀察者的設計模式,這是一種建立鬆散耦合代碼的技術。
□對象發行就緒事件,用來表示該對象聲明周期中某個有趣的時刻到了。
□其他對象可以觀察該對象,等待有趣的時刻到來並通過運行代碼來響應。
②觀察者模式由兩類對象組成:主體和觀察者。
□主體負責發布事件,同時觀察者通過訂閱這些事件來觀察主體。
□主體並不知道觀察者的任何事情,它可以獨立自存在並正常運作即使觀察者不在。
③自訂事件:建立一個管理事件的對象,讓其他對象監聽那些事件。 複製代碼 代碼如下:function EventTarget(){
this.handlers = {};
}
EventTarget.prototype = {
constructor : EventTarget,
addHandler : function(type,handler){
if(typeof this.handlers[type] == "undefined"){
this.handlers[type] = [];
}
this.handlers[type].push(handler);
},
fire : function(event){
if(!event.target){
event.target = this;
}
if(this.handlers[event.type] instanceof Array){
var handlers = this.handlers[event.type];
for(var i=0,len=handlers.length; i<len; i++){
handlers[i](event);
}
}
},
removeHandler : function(type, handler){
if(this.handlers[type] instanceof Array){
var handlers = this.handlers[type];
for(var i=0,len=handlers.length; i<len; i++){
if(handlers[i] === handler){
break;
}
}
Handlers.splice(i,1);
}
};

④使用EventTarget類型的自訂事件可以如下使用: 複製代碼 代碼如下:function handleMessage(event){
alert("message received:" + event.message);
}
//建立一個新對象
var target = new EventTarget();
//添加一個事件處理常式
target.addHandler("message",handleMessage);
//觸發事件
target.fire({type:"message",message:"hello world!"});
//刪除事件處理常式
target.removeHandler("message",handleMessage);

⑤使用執行個體 複製代碼 代碼如下:function Person(name,age){
eventTarget.call(this);
this.name = name;
this.age = age;
}
inheritPrototype(Person, EventTarget);
Person.prototype.say = function(message){
this.fire({type:"message", message:message});
};
function handleMessage(event){
alert(event.target.name + "says: " + event.message);
}
//建立新person
var person = new Person("Nicholas",29);
//添加一個事件處理常式
Person.addHandler("message",handleMessage);
//在該對象上調用1個方法,它觸發訊息事件
person.say("Hi there");

4.拖放
功能:①拖放②添加了自訂事件 複製代碼 代碼如下:var DragDrop = function(){
var dragdrop = new EventTarget();
var dragging = null;
var diffX = 0;
var diffY = 0;
function handleEvent(event){
//擷取事件和對象
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
//確定事件類型
switch(event.type){
case "mousedown" :
if(target.className.indexOf("draggable")>-1){
dragging = target;
diffX = event.clientX - target.offsetLeft;
diffY = event.clientY - target.offsetTop;
dragdorp.fire(
{
type:"dragstart",
target : dragging,
x : event.clientX,
y : event.clientY
}
);
break;
case "mousemove" :
if(dragging !== null){
//擷取事件
event = EventUtil.getEvent(event);
//指定位置
dragging.style.left = (event.clientX - diffX) + "px";
dragging.style.top = (event.clientY - diffY) + "px";
//觸發自訂事件
dragdrop.fire(
{
type : "drag",
target : dargging,
x : event.clientX,
y : event.clientY
}
);
}
break;
case "mouseup" :
dargdorp.fire(
{
type : "dragend",
target : dragging,
x : event.clientX,
y : event.clientY
}
);
dragging = null;
break;
}
}
//公用介面
dragdrop.enable = function() {
EventUtil.addHandler(document, "mousedown", handleEvent);
EventUtil.addHandler(document, "mousemove", handleEvent);
EventUtil.addHandler(document, "mouseup", handleEvent);
};
dragdrop.disable = function(){
EventUtil.removeHandler(document, "mousedown", handleEvent);
EventUtil.removeHandler(document, "mousemove", handleEvent);
EventUtil.removeHandler(document, "mouseup", handleEvent);
};
return dragdrop;
}();

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.