JavaScript高级程序设计 学习笔记 js高级技巧

第十八章 高级技巧
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;
}();

(0)

相关推荐

  • javascript学习随笔(使用window和frame)的技巧

    JavaScript允许创建和打开代表HTML文本, form对象和frame的窗口. window对象是JavaScript客户层次结构的最顶层对象, form元素和全部JavaScript代码都是存在于文档中,而文档被装载进窗口. 为了理解窗口怎样工作,你可以控制操作这些窗口. 打开和关闭窗口 当用户启动(launch)Navigator时,将自动创建一个窗口.用户还可以使用Navigator的File菜单上的New Web Browser打开一个窗口, 可以用Navigator的File菜

  • JavaScript编程学习技巧汇总

    本文实例为大家分享了JavaScript编程学习技巧,供大家参考,具体内容如下 1.变量转换 varmyVar="3.14159", str=""+myVar,//tostring int=~~myVar,//tointeger float=1*myVar,//tofloat bool=!!myVar,/*toboolean-anystringwithlength andanynumberexcept0aretrue*/ array=[myVar];//toarra

  • javascript学习总结之js使用技巧

    1 假如浏览器不支持JavaScript怎么办? a.为什么浏览器会不支持?大部分浏览器都有禁用脚本的功能,例如chrome. b.在js被禁用的情况下要保证网页仍能实现它的核心功能(关键的用户需求) 例子:在一个新窗口里打开链接,可以使用BOM的open()方法 function popUp(winURL) { window.open(winURL, "popup", "width=,height="); } 具体的js实现有以下几个方案: 方案一:使用javas

  • javascript学习笔记之10个原生技巧

    1.原生JavaScript实现字符串长度截取 复制代码 代码如下: function cutstr(str, len) {    var temp;    var icount = 0;    var patrn = /[^\x00-\xff]/;    var strre = "";    for (var i = 0; i < str.length; i++) {        if (icount < len - 1) {            temp = str

  • JavaScript 学习技巧

    转化为Boolean类型 所有JavaScript中的值都能隐式的转化为Boolean类型,比如: 0 == false; // true 1 == true; // true '' == false // true null == false // true 但是这些值都不是Boolean类型.因此当我们使用三个等于号进行比较时: 0 === false; // false 1 === true; // false '' === false // false null === false //

  • 快速学习JavaScript的6个思维技巧

    我们在学习JavaScript,或其他任何编码技能的时候,往往是因为这些拦路虎而裹足不前: 有些概念可能会造成混淆,尤其当你是从其他语言转过来的时候. 找不到时间(有时是动力)学习. 很容易忘记已经理解了的东西. 工具多又在不断变化,所以不知道从哪里开始. 幸运的是,这些拦路虎是可以被识别,并消灭的.在这篇文章中,我将介绍六个思维技巧来帮助你更快地学习JavaScript,并成为一个更快乐.更富有成效的程序员. 1.不要让未来的决策阻止你现在前进的方向 很多人学习JavaScript,问的第一个

  • JavaScript 学习笔记一些小技巧

    一.JavaScript 基础 1.try...catch 使用小写字母.大写字母会出错. 2.Throw 声明 throw 声明的作用是创建 exception(异常).你可以把这个声明与 try...catch 声明配合使用,以达到控制程序流并产生精确错误消息的目的. 语法:throw(exception)exception 可以是字符串.整数.逻辑值或者对象. 注意:使用小写字母编写 throw.使用大写字母会出错! 3.反斜杠用来在文本字符串中插入省略号.换行符.引号和其他特殊字符. 下

  • JavaScript高级程序设计 学习笔记 js高级技巧

    第十八章 高级技巧 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");

  • JavaScript高级程序设计 读书笔记之八 Function类及闭包

    Function类 定义 Function类可以表示开发者定义的任何函数,用Function类直接创建函数的语法如下: var function_name=new Function(agrument1,agrument2,...,argumentN,function_body); 每个argument都是一个参数,最后一个参数是函数主体(要执行的代码). 示例: 复制代码 代码如下: function sayHi(sName,sMessage){ alert("Hello "+sNam

  • JavaScript高级程序设计 阅读笔记(十七) js事件

    一.事件流 IE中是冒泡型事件,即从最特定的事件目标到最不特定的事件目标. Netscape Navigator使用的是捕获型事件,这个跟IE中采用的冒泡型事件相反. DOM事件流同时支持两种事件模型,但捕获型事件先发生. 二.事件处理函数/监听函数 事件是用户或浏览器自身进行的特定行为.这些事件都有自己的名字,如click.load.mouseover等. 事件处理函数有两种分配方式:在JavaScript中或者在HTML中. 如果在JavaScript中分配事件处理函数,则首先要获得要处理的

  • JavaScript高级程序设计 阅读笔记(十九) js表格排序

    排序代码 复制代码 代码如下: function SortTable(sTableID, iCol, sDataType){ this.oTable=document.getElementById(sTableID); this.oTBody=this.oTable.tBodies[0]; this.colDataRows=this.oTBody.rows; this.aTRs=[]; this.iCol=iCol; this.sDataType=sDataType; } SortTable.p

  • JavaScript高级程序设计阅读笔记(十六) javascript检测浏览器和操作系统-detect.js

    检测浏览器的方式 1.对象特征检测法:判断浏览器能力的通用方法.如果更关注浏览器的能力而不在乎它的实际身份,就可以使用这种检测方法.常见的原生Ajax写法中就用这种方法来创建XMLHttpRequest: 复制代码 代码如下: IXHR: function(){ if(window.ActiveXObject){ XHR=new ActiveXObject('Microsoft.XMLHTTP'); }else if(window.XMLHttpRequest){ XHR=new XMLHttp

  • JavaScript高级程序设计 阅读笔记(二十) js错误处理

    一.错误分类 1.语法错误:也称解析错误,发生在传统语言的编译时,在JavaScript中发生在解释时.这些错误是由代码中的意外字符直接引起的,然后就不能直接编译/解释.发生语法错误时,就不能继续执行代码.在JavaScript中,只有在同一个线程中的代码会受语法错误的影响.在其他线程中的代码和其他外部引用的文件中的代码,如果不依赖于包含错误的代码,则可以继续执行. 2.运行时错误:也称为异常(exception,在编译期/解释器后).此时,问题并不出在代码的语法上,而是,尝试完成的一个操作,在

  • JavaScript高级程序设计 阅读笔记(十四) js继承机制的实现

    继承 继承是面向对象语言的必备特征,即一个类能够重用另一个类的方法和属性.在JavaScript中继承方式的实现方式主要有以下五种:对象冒充.call().apply().原型链.混合方式. 下面分别介绍. 对象冒充 原理:构造函数使用this关键字给所有属性和方法赋值.因为构造函数只是一个函数,所以可以使ClassA的构造函数成为ClassB的方法,然后调用它.ClassB就会收到ClassA的构造函数中定义的属性和方法. 示例: 复制代码 代码如下: function ClassA(sCol

  • JavaScript高级程序设计 阅读笔记(十八) js跨平台的事件

    跨平台的事件EventUtil对象 EventUtil: 复制代码 代码如下: var EventUtil={ addEventHandler:function(oTarget, sEventType, fnHandler){ if(oTarget.addEventListener){ oTarget.addEventListener(sEventType,fnHandler,false); } else if(oTarget.attachEvent){ oTarget.attachEvent(

  • JavaScript高级程序设计 阅读笔记(十二) js内置对象Math

    Math对象的属性 E:值e,自然对数的底 LN10:10的自然对数 LN2:2的自然对数 LOG2E:以2为底E的对数 LOG10E:以10为底E的对数 PI:值派 SQRT1_2:1/2 的平方根 SQRT2:2的平方根 Math对象的方法:最大值与最小值 min()&&max()用于取一组数中的最小值跟最大值. 示例: 复制代码 代码如下: var iMax=Math.Max(1,2,3); alert(iMax);//outputs 3 var iMin=Math.Min(1,2,

  • JavaScript高级程序设计 阅读笔记(十三) js定义类或对象

    工厂方式 创建并返回特定类型的对象. 复制代码 代码如下: function createCar(sColor,iDoors,iMpg){ var oTempCar=new Object(); oTempCar.color=sColor; oTempCar.doors=iDoors; oTempCar.mpg=iMpg; oTempCar.showColor=function(){ alert(this.color); } return oTempCar; } 调用示例: 复制代码 代码如下:

随机推荐