來自《javascript高級程序設計》
- 安全類型的檢測
多個iframe存在多個全局作用域,在使用value instanceof array時,必須與array構造函數在同一個全局作用域並且是一個數組。
Object.toString方法可放回[object nativeconstructorname]格式的字符串。通過這個函數測試某個值是不是原生函數、正則表達式。
function isArray(value){
return Objet.prototype.toString.call(value) == '[Object Array]';
}
function isFunction(value){
return Object.prototype.toString.call(value)=='[Object Function]'
}
function isRegExp(value){
return Object.prototype.toString.call(value)=='[Object RegExp]'
}
- 作用域安全的構造函數
確保構造函數this指向指定對象。
function Person(name){
if(this instanceof Person){
this.name=name;
}else{
return new Person(name);
}
}
let p1=new Person('p1');
console.log(window.name,p1.name)
let p2=Person('p2');
console.log(p2.name)
//繼承可能會被破壞,使用原型鏈和寄生組合可解決這個問題
function Polygon(sides){
if(this instanceof of 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();
let rect=new Rectangle(5,10);
console.log(rect.sides)
- 函數柯里化
用於創建已經設置好了一個或者多個參數的函數。使用閉包返回函數。動態創建:調用另一個函數併爲它傳入要傳柯里化函數和必要參數。
// 函數柯里化
// 將返回的函數進行排序。
function curry(fn){
var args=Array.prototype.slice.call(arguments,1);
// arguments並非數組,可通過下標獲取參數,無slice方法
return function(){
var innerArgs=Array.prototype.slice.call(arguments);
var finalArgs=args.concat(innerArgs);
return fn.apply(null,finalArgs);//執行環境可能被破壞null
}
}
//綁定給定環境
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);
}
}
- 定時器settimeout,setinterval
在特定的時間後將代碼插入到主隊列,不能保證代碼一定在指定時間後運行。
setinterval:js引擎將處理:當沒有改定時器的任何其他代碼實例時,纔將定時器代碼添加到隊列中,確保定時器代碼加入到隊列的最小時間間隔爲指定間隔。存在缺點:定時器代碼未執行完,又向隊列插入新的定時器代碼。
使用鏈式setTimeout可避免:
//保證在下一次定時器代碼執行之前,至少要等到指定的間隔
setTimeout(function(){
//處理代碼
setTimeout(arguments.callee,interval);
},interval);
- yield process
js代碼的長時間運行腳本制約。德朗的任務可通過定時器數組分割array chunking技術。爲要處理的項目創建一個隊列,然後使用定時器去除下一個要處理的項目進行處理,接着再設置另一個定時器。
// 基本模式
setTimeout(function(){
var item=array.shift();
process(item);
if(array.length>0){
setTimeout(arguments.callee,100)
}
},100);
function chunk(array,process,context){
setTimeout(function(){
var item=array.shift();
process.call(context,item);
if(array.length>0){
setTimeout(arguments.callee,100)
}
},100)
}
// 函數字節流
var processor={
timeroutId:null,
performProcessing:function(){
//實際執行的代碼
},
process:function(){
clearTimeout(this.timeroutId);
var that=this;
this.timeroutId=setTimeout(function(){
that.performProcessing();
},100)
}
}
//執行
process.process();
//簡化
function throttle(method,context){
clearTimeout(method.tId);
method.tId=setTimeout(function(){
method.call(context);
},100)
}
//可引用語window.onresize時更改大量dom元素樣式
- 自定義事件
//自定義事件--創建一個管理事件的對象,讓其他對象監聽那些事件。
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){
for(var i=0,len=handlers.length;i<len;i++){
if(handlers[i]==handler){
break;
}
}
handlers.splice(i,1);
}
}
}