存档

文章标签 ‘javascript’

文件管理控件elfinder中的一个小bug

2015年6月27日 没有评论

最近项目中用到了elfinder这个控件,用下来总体效果不错,可配置性很强,也能够根据自己的需求增加自定义菜单,但是在测试的过程中发现了一个小bug,记录一下。

如果用firefox浏览器访问www.elfinder.org,选中Test文件夹后,用鼠标悬浮到上传文件的icon上,本来应该显示“Upload files”的tooltip却显示为了“No files selected”,看了下原因,貌似是firefox浏览器在解析如下html代码的时候,会将子元素input的tooltip覆盖父元素的title属性。

<div class="ui-state-default elfinder-button ui-state-disabled" title="Upload files">
<form style="display: none;">
<input type="file" multiple="multiple" />
</form>
</div>

 

原因找到了就好办了,只需要把input的title属性动态地设置成”Upload files”就可以了,可以在init事件中添加该行为。

$(".elfinder-button form input[type='file']").attr('title', nls.uploadFiles);

 

Javascript中函数前面感叹号,加号的意思

2015年5月12日 没有评论

在Javascript的开发以及学习过程中,我们经常能看到函数前面加个感叹号或者是加号的写法。

比如:

bootstrap的JS组件就是采用了加号的写法:https://github.com/twbs/bootstrap/blob/master/dist/js/bootstrap.js

再比如:

大众点评官网编译出的好多JS插件都是采用了感叹号的写法。

那么为什么要加感叹号以及加号呢?原因很简单,先看下面的代码,写过jQuery插件的都知道jQuery插件的套路写法就是:

(function($) {         
  //...  
})(jQuery);

在function外面多加的一个括号是为了保证这个匿名函数能够被当做函数表达式来执行,如果不添加function外层的括号的话,浏览器就会报错。

我们再回到函数前加感叹号以及加号的问题,其实道理是一样的,就是为了保证匿名函数能够被当做函数表达式来执行而已,而且这种写法有一丝丝好处是比较清楚地标示了这个匿名函数,大括号的写法你还得在一大坨代码中去寻找右括号在哪里,如果没有编辑器的帮助的话有点费眼力。

分类: Javascript, 语言 标签:

在Javascript中应该如何判断数据类型

2015年5月8日 没有评论

引子


在实际的前端项目中,我们经常需要判断某个数据是否是数组,或者是否是函数,自己之前经常的写法就是instanceof,但是在看美国peer的代码的时候,看到了一个这样的写法Object.prototype.toString.call(x) === ‘[object Array]‘,感觉很奇怪,于是就搜索了一下,就有了这篇博文。

 

为什么不用typeof


初学javascript的话,一定会有这个疑惑,typeof和instanceof,这两货到底有啥区别?实际上typeof的返回值只有六个: undefined, boolean, number, string, function以及object,无法判断数组,但是呢,instanceof就可以,所以很多情况下使用instanceof就可以了。

 

那干嘛不用instanceof


确实在很多情况下,instanceof就可以了,但是呢,如果一个页面包含多个frame的话,这样的判断方法就失效了,我们来看下面这个例子:

v instanceof Array

如果v是来源于另外一个frame的数组对象,那么此时该表达式返回的是false,因为v只是anotherFrame.contentWindow.Array的实例,并不是当前frame的数组的实例。

 

我该用啥


如果是原生的javascript的话,用Object.prototype.toString.call(x) === ‘[object Array]‘类似的语句就可以很好地判断对象的数据类型了。

如果在项目中使用到了underscore或者是lodash’的话,那么恭喜你,你可以使用它们提供的isArray, isNumber, isFunction, isRegExp等方法来判断数据类型。

如果你的项目是nodejs的话,那么你可以使用util这个模块:

var util = require("util");
var a = [];
console.log(util.isArray(a));

浅谈程序语言中的鸭子类型(Duck Typing)

2015年4月13日 没有评论

引子


今天在看Underscore的API文档时遇到了一个术语”Duck Typing”,面向对象的编程思想学习了这么久,竟然不知道这个术语是什么意思,赶紧google了一把脑补一下。

 

起源


wiki的解释来看,这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,“鸭子测试”可以这样表述:

“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

 

阐释


wiki上的定义如下:

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。

wiki上的定义比较绕口,个人的理解就是你不需要去严格地继承自某个类,但是你可以实现该类所具有的一些特征,让这个类即使是鸟,看起来像鸭子就行。

 

例子


个人经常用的动态语言就是Python和Javascript。所以分别找了这两个语言的例子帮助大家进行理解。

 

Python

Python的例子满大街都是,网上抄了一个,如下所示:

#coding=utf-8  
class Duck:  
    def quack(self):  
        print "Quaaaaaack!"  
 
class Bird:  
    def quack(self):  
        print "bird imitate duck."  
 
class Doge:  
    def quack(self):  
        print "doge imitate duck."  
 
def in_the_forest(duck):  
    duck.quack()  
 
duck = Duck()  
bird = Bird()  
doge = Doge()  
for x in [duck, bird, doge]:  
    in_the_forest(x)

这个例子实在简单,我就不多解释了,大意就是Duck,Bird以及Doge虽然没有继承自同一个父类,但是都具有quack方法。

 

Javascript

Javascript的例子来源于Stackoverflow,问题的回答者写的十分风趣,用流行的话说,就是萌萌哒…

链接如下:http://stackoverflow.com/questions/12762550/example-of-javascript-duck-typing

 

回顾Underscore


在Underscore的文档中,有这么一段话涉及到了Duck Typing:

Note: Collection functions work on arrays, objects, and array-like objects such asargumentsNodeList and similar. But it works by duck-typing, so avoid passing objects with a numeric length property. It’s also good to note that an each loop cannot be broken out of — to break, use _.find instead.

意思就是说underscore的collection相关的函数是由Duck typing的方式来编写的,不能传入带有length属性的对象,否则就不正常工作了。

OK,那么我们再来看下Underscore的源代码,我们找个比较简单的each函数来看下,下面的函数依赖于传入参数obj的length,如果obj是个数组的话,那当然没什么问题,但是如果传入参数是一个{length: 100},那就只能呵呵了。

_.each = _.forEach = function(obj, iteratee, context) {
    if (obj == null) return obj;
    iteratee = createCallback(iteratee, context);
    var i, length = obj.length;
    if (length === +length) {
      for (i = 0; i &lt; length; i++) {
        iteratee(obj[i], i, obj);
      }
    } else {
      var keys = _.keys(obj);
      for (i = 0, length = keys.length; i &lt; length; i++) {
        iteratee(obj[keys[i]], keys[i], obj);
      }
    }
    return obj;
  };

 

使用JS实现client side include

2011年8月26日 没有评论

上一篇日志从网上转载了一个开启SSI的日志,开启了SSI以后,可以让许多页面包含共有的header以及footer,这样在做修改的时候只需要修改一个地方就可以了,十分方便。但是在实际使用中,有可能会出现无法开启SSI的情况。

比如,你向别人租用了一台虚拟主机,而该虚拟主机的管理员在httpd.conf中并没有设置Includes Option,同时很悲剧的他又设置了AllowOverrides为None,这样即使你使用.htacesss也就没有办法开启SSI了,so,这个时候该肿么办,笔者之前的做法是在一台测试服务器上开启SSI,并书写包含有SSI指令的web页面,当在向生产服务器部署的时候则写了一个python脚本将SSI指令替换生成静态html。但是这样子做的一个缺点在于,测试服务器与生产服务器之间的数据就无法进行同步,每次需要大规模修改页面外观的时候,必须对测试服务器上的SSI页面进行处理以后才可以部署到生产服务器上,十分繁琐。

于是,这篇日志的主角登场了~使用Javascript实现client side include,原理很简单,就是将header和footer的内容用document.write输出,然后在每个页面中包含相应的js文件即可。