jQuery在1.5开始引入deferred(延迟),简单说,deferred对象就是jQuery的回调函数解决方案。
jQuery1.5中,Deferred对象提供一种方式来注册多个回调,添加到自已管理的回调队列中,调用适当的回调队列,并转达同步或异步函数的成功或失败状态。
deferred对象有三种执行状态:未完成(pending),已完成(resolved)和已失败(rejected)
API概览:
deferred object = {
always(alwaysCallbacks [, alwaysCallbacks])
done(doneCallbacks)
fail(failCallbacks)
isRejected()
isResolved()
notify( args )
notifyWith(context, [args])
pipe([doneFilter] [, failFilter] [, progressFilter] )
progress( progressCallbacks )
reject([args])
rejectWith(context, [args])
resolve([args])
resolveWith(context, [args])
state()
then(doneCallbacks, failCallbacks [, progressCallbacks])
promise([target])
}
Read more »
最近两天为实现一个跨域通信的问题,对这个问题进行了相关的学习,心得一二,在此分享。
window.postMessage()
方法
HTML5给我们带来了安全的跨域通信接口,即window.postMessage()方法。它方法原型是:
window.postMessage(msg, domain);
该方法的浏览器支持情况:E8+, FF3+, Chrome, Safari,且在IE下,msg参数必须是string,不能是object.由此可见,我们只要考虑IE6,IE7下的跨域实现。
一、方案一
使用window.postMessage + window.opener实现,该方式是利用IE6,7 opener hack的方式实现跨域,可以算一个安全漏洞。
实现方式:
- 1、www.a.com/a.html 和 www.b.com/b.html,b.html被a.html嵌套在iframe里面。
- 2、首先两个页面各设置目标通信页面的opener = {};opener对象可包含一个方法,这样当前页面可以直接调用目标页面的opener内的方法,并传递参数。
www.a.com/a.html
var otherWindow = document.getElementById("ifr_a").contentWindow;
otherWindow.opener={
postMessage:function(str){
alert(str);
}
}
www.b.com/b.html
parent.opener={
postMessage:function(str){
alert(str);
}
}
发送消息:
window.opener.postMessage(message);
这样目标页面就能收到消息了。
我做了一下JS的封装,大家可以直接下载使用:crossMessageEvent_opener.js
下载:crossMessageEvent_opener.js
- 1、a.html和b.html分别引用该JS
- 2、分别进行初始化CrossMessageEvent.init(otherWindow); //otherWindow 为目标窗口的window对象
- 3、发送消息CrossMessageEvent.postMessage(otherWindow, message, targetOrigin);
otherWindow:为目标窗口的window对象
message:消息内容,可以是object
targetOrigin:目标窗口的域 [可选]
CrossMessageEvent.receiveMessage(funciton(event){
alert(event.data);
});
该方法的优点:
不需要使用代理页面,简单直接。
该方法的缺点:
只要打过微软的安全补丁.kb2497640就不能用了。
Read more »
在JS中,定义函数有两种方式,函数语句和函数表达式;
函数语句定义:
function testB(){
console.log("B");
}
函数表达式定义:
var testA = function(){
console.log("A");
}
1、作用域提升
在定义位置上,函数语句的方式定义,会将其作用域名提升至顶端,而函数表达式定义不会,必须先定义后执行。看下面的例子:
testB();
testA();
var testA = function(){
console.log("A");
}
function testB(){
console.log("B");
}
testA无法执行,因为找不到定义的函数,要想testA执行,必须将它的函数表达式定义放到执行时的前面。
2、this关键词的指向
在JS中,函数语句定义和函数表达式定义,this
关键词都会指向其运行时的引用,两者没有区别。
而在AS3中,函数语句定义中的this始终指向当前函数定义的域,而函数表达式定义中的this
会随着附加对象的变化而变化,且可以使用call()
和apply()
改变其this的指向。
这一点区别非常重要,特别对于js和as同时使用的前端开发来讲,掌握两者的其础知识,能避免你犯错!
Read more »
一、构造函数法
在JS中,虽然没有严格的面向对象编程,但程序的设计还是有面向对象的味道。所有引用类型的数据,都是基于object;Array类型的数据,typeof时也会显示object;这给我们判断array类型,带来了不便。
细想一下array的创建过程,var arr = new Array(1,2,3);
或var arr = [1,2,3];
实际上是创建了一个Array对象的实例,也就是说实例所对应的构造函数应该是Array;根据此原理,判断方法如下:
function isArray(object){
return object && typeof object==='object' &&
Array == object.constructor;
}
注意:
该种判断方法,被判断的array必须是在当前页面声明的!比如,一个页面(父页面)有一个框架,框架中引用了一个页面(子页面),在子页面中声明了一个array,并将其赋值给父页面的一个变量,这时判断该变量,Array == object.constructor;
会返回false;
原因:
二、特性判断方法
即然上述方法,存在一定的缺陷,我们可根据数组的一些特性来判断其类型,代码如下:
function isArray(object){
return object && typeof object==='object' &&
typeof object.length==='number' &&
typeof object.splice==='function' &&
!(object.propertyIsEnumerable('length'));
}
有length和splice并不一定是数组,因为可以为对象添加属性,而不能枚举length属性,才是最重要的判断因子。
Read more »
一、jLinq
jLinq 是一个用来编写JavaScript对象数组查询的JavaScript库,可以对数组对象执行类似于LINQ风格的查询。
项目主页:http://www.hugoware.net/Projects/jLinq
二、jquery-filedrop
filedrop是一个html5图片拖拽上传的JS框架,能批量将电脑上的图片拖拽至浏览器,读取图片的二进制,并组装成post包,配合后台程序完成图片上传。
使用HTML5上传文件其实综合使用了3种技术,新的File Reader API,还有新的Drag&Drop API,以及AJAX技术(包含2进制的数据传输),filedrop对这三个功能进行的了整合封装。
项目地址:https://github.com/weixiyen/jquery-filedrop
Read more »
初次接触easyui,使用datagrid时绑定数据时,大多人骂他的设计很烂,一定要在URL中指定一个json文件,或者请求一个服务器端动态生成的json程序,而在实际的开发中,后台程序很少愿意给到完全符合前台开发理想中的数据结构。
其实不然,我们接触一个新的东西时,遇到问题,总是习惯于到搜索引擎去寻求答案,而不愿意从API中找到答案,当然大家没这么多时间耗在这么长的英文API中。
easyui,datagrid使用,其实可以读取JS本地拼接组合的JSON对象的。
<table id="tt"></table>
$('#tt').datagrid({
width:300,
heigth:"auto",
fitColumns:true
});
var jsdata = {total:1,rows:[{name:"",value:""}]}
$('#tt').datagrid("loadData",jsdata);
jQuery EasyUI中文帮助手册(API):http://www.phptogether.com/juidoc/
jQuery EasyUI英文官方手册(API):http://www.jeasyui.com/documentation/index.php
Read more »
用canvas做一个loading icon,需要用到圆周上等分点坐标的计算,算法如下:
var loadPoint = [];
function getLoadPoint(r,ox,oy,count){
var radians = (Math.PI / 180) * Math.round(360 / count);
for(var i = 0; i < count; i++){
var x = ox + r * Math.sin(radians * i);
var y = oy + r * Math.cos(radians * i);
loadPoint.unshift({x:x,y:y});
}
}
Read more »
js bind 函数 使用闭包保存执行上下文
bind()主要具有两个重要作用:
(1)一般地,方法中的this关键字总是指向调用此方法的对象,这就造成this显得很不稳定,而使用bind()方法能够保证无论什么时候调用此方法,this关键字总是指向你所要的对象.
(2)提供两次添加参数的机会.第一次是在使用bind()方法的时候,第二次是调用bind()方法返回的句
prototypejs框架中的实现方式:
Function.prototype.bind = function() {
var __method = this;
var args = Array.prototype.slice.call(arguments);
var object=args.shift();
return function() {
return __method.apply(object,
args.concat(Array.prototype.slice.call(arguments))
);
}
}
用法实例:
var name = "window";
var obj = {
name: 'JSON',
getName: function() {
alert(this.name);
}
};
function runFun(fun) {
fun();
}
var getName2 = obj.getName.bind(obj);
runFun(obj.getName);
runFun(getName2);
Read more »
JS没有严格的类似JAVA的类概念,但可以通过原型链实现类。
通常意义上,推荐使用在构造函数中接受属性值,在原型链上注册方法属性。详情可参考《JavaScript高级程序设计(第2版)》
类似以下代码:
var myClass = function(a, b, c){
this.a = a;
this.b = b;
this.c = c;
}
myClass.prototype = {
f1: function(){alert(this.a);},
f2: function(){alert(this.b);},
f2: function(){alert(this.c);}
}
var classA = new myClass(1,2,3);
classA.f1();
匿名函数
顾名思义,匿名函数就是没有实际名字的函数。
大家知道小括号的作用吗?小括号能把我们的表达式组合分块,并且每一块,也就是每一对小括号,都有一个返回值。这个返回值实际上也就是小括号中表达式的返回值。所以,当我们用一对小括号把匿名函数括起来的时候,实际上小括号对返回的,就是一个匿名函数的Function对象。因此,小括号对加上匿名函数就如同有名字的函数般被我们取得它的引用位置了。所以如果在这个引用变量后面再加上参数列表,就会实现普通函数的调用形式。
如 (function(){alert(“匿名函数”);});
但小括号返回的仅是函数表达式,函数并没有运行起来。要运行函数表达式在后再再加上();
变成 (function(){alert(“匿名函数”);})();
这样就产生了一个困扰,这样写会产生闭包吗?大家都知道闭包对于GC的垃圾回收机制有影响,建议少用闭包。
下面我们就来探讨一下。
以我的理解来说吧。是否应用了闭包特性,必须确定该段代码有没有最重要的要素:未销毁的局部变量。
只能说这种写法有闭包的特性,只否形成闭包,还要看有没有未销毁的局部变量。
匿名函数封装类
(function(){
var myClass = function(a, b, c){
this.a = a;
this.b = b;
this.c = c;
}
myClass.prototype = {
f1: function(){alert(this.a);},
f2: function(){alert(this.b);},
f2: function(){alert(this.c);}
}
window.myClass = myClass;
})();
var classA = new myClass(1,2,3);
var classB = new myClass(10,20,30);
classA.f1();
classB.f1();
其中window.myClass = myClass;这一段,也可以使用return 抛可供调用的API接口。
Read more »
以下的几个小技巧,其实考察的是对JS基础知识的掌握和理解。基础的东西一定要打牢固,才能向使你的编码能力有台阶性的上升。
1、简短取当前时间戳。
普通青年的做法:
var time = new Date().getTime();
文艺青年的做法:
var time = (+(new Date));
var time = +(new Date);
效果是一样的,但是文艺青年的做法,明显优雅一些,不过可读性视各位的基础而定。
原理:
大家知道小括号的作用吗?小括号能把我们的表达式组合分块,并且每一块,也就是每一对小括号,都有一个返回值。(new Date)其实就是返回当前的Date对象。
一元加操作符(+),放在数字前面,对数值不会产生任何影响。但放在非数值类型的前面,相当于Number()转型函数。+(new Date)就返回了时间戳数字。但为什么外面还需要一对括号呢,如果用于赋值操作,可有可无,但用于字符串连接操作时,一定要加上。
2、布尔操作符的妙用
判断一个字符串为空
var str = “”;
普通青年的做法:
if(str==''){
alert("字会串是空的哦!");
}
文艺青年的做法:
if{
alert;
}
原理:
逻辑非(!)操作符,放在值前面,无论这个值是什么数据类型,这个操作符都会返回一个布尔型,然后再对其求反。
两个”!!”,实际上就相当于应用Boolean()函数转型。
3、逻辑与操作符(&&)的妙用
a(),和 b(); b的执行需a()返回值为true才能执行,否则不执行。
普通青年的做法:
if){
b;
}
文艺青年的做法:
a && b;
原理:
逻辑与属于短路操作,如果第一个操作数能够决定结果,那么不会对第二个操作数进行求值。
当a();返回false时,就注定整个表达式为false,无需运行b();
Read more »