javascript语言精粹 笔记一

作者:yaya | 时间:2009年9月15日 | 分类 学海无涯 | 标签 javascript | 1回复

最近在看Douglas Crockford大师的《JavaScript语言精粹》。于是就胡乱记录下自己的一些理解与认识,这其中不免有说得不好甚至错误的地方。但是我相信,随着理解的深入,这些问题会逐渐减少的。

此书主要就JavaScript的精华,鸡肋和糟粕做了详细的分析阐述。将其优雅的地方展现得淋漓尽致,而对于其糟粕,也显示出了其危害性。

JavaScript是基于原型继承的语言。也就是说,对象可以直接从其他对象继承属性。其语言是无类别而言的。除了简单类型(包括数字、字符串、布尔值、null、underfined)外都是对象。其中的函数也是对象。对象就是名称与对应值所组成的集合。每个对象都拥有一个连到原型对象的隐藏连接。
 对象字面量(花括号中的名称与其对应值组成对,属性名在编译时候了解到。型如下)产生的对象连接到Object.prototype。函数对象连接到Function.Prototype(其原型对象也是连接到Object.prototype)。每个函数创建的时候,会有两个隐藏属性:函数上下文和实现函数行为的代码。而其中的上下文是很重要的东东,其在函数访问外部函数的实际变量(并且不是复制的)的时候会让人觉得很神奇。一个函数可以访问它被创建时候的上下文环境,当然各种变量也就不再话下。这种情况称之为闭包。有时候函数已经返回了,但是它的变量还会保留,这中情况其实是很常见的。看起来也很帅。很经典的例见下。

对象字面量
  1. var empty_object = {};
  2.  
  3. var card_object = {
  4.    "first-name":"yaya",
  5.    "last-name":"zinkey"
  6. };

 
这个例子目前是当点击一个节点时,弹出一个对话框显示的节点的序号。可是呢。前者并不能达到这样的效果,并且老是得到节点的数目。原因即是绑定的变量i随着循环的递增已经变化成了节点的数目。在函数构造时候,i就等于节点的数目。第一个例子中,我们可以看到的是onclick得到赋值是一个函数,而这个函数是弹出i的对话框。但其本身就可以访问到var i的实际的值(上下文),所以最终得不到预期的效果。而第二个例子呢?我们可以看到,当定义了一个函数,就传递i执行,函数返回的是事件处理函数,其本身是和传递进去的i绑定的。而不是var i。可以看到(i),用()运算符立即调用刚刚构造出来的函数,而这个被调用创建并返回的函数才是给予onclick的处理函数。

很经典的例子
  1. var add_the_handlers = function (nodes){
  2.    var i;
  3.    for (i=0;i<nodes.length;i+=1){
  4.      nodes[i].onclick = function(e){
  5.       alert(i);
  6.      }
  7.    }
  8. };
  9.  
  10. //另外一个
  11. var add_the_handlers = function (nodes){
  12.    var i;
  13.    for (i=0;i<nodes.length;i+=1){
  14.      nodes[i].onclick = function(i){
  15.         return function(e){
  16.           alert(e);
  17.         };
  18.      }(i);
  19.    }
  20. };

一下是method定义新方法

用method方法定义新方法
  1. Function.prototype.method = function (name,func){
  2.    this.prototype[name] = func;
  3.    return this;
  4. }

以后就直接通过method来定义新的方法。

如:

trim
  1. String.method("trim",function(){
  2.    return this.replace(/^s+|s+$/g,'');
  3. });

但是这样来写method,会忽略一个问题:基本类型的原型是公共结构,在类库混用时要考虑其已有方法。
所以,修改method为: 

新method
  1. Function.prototype.method = function (name,func){
  2.    if (!this.prototype[name]){
  3.       this.prototype[name] = func;
  4.     }
  5. };
  6. //或者
  7. Function.prototype.method = function (name,func){
  8.    if (!this.prototype.hasOwnProperty[name]){
  9.       this.prototype[name] = func;
  10.     }
  11. };

hasOwnProperty将筛选出继承出来的属性,这样就可以避免混用的发生。

 

javascript浏览器判断

作者:yaya | 时间:2009年9月12日 | 分类 学海无涯 | 标签 javascript | 1回复

 好久没写过学海无涯里面的东西了。开始!

今天上网看到关于javascript判断浏览器的东东,于是就去看了关于它的一些写法。最先就是去李战csdn上看他书的介绍。那说是彩印的,所以当然就贵啦。看封面就很好玩。



他写道了这个东西,就把代码给复制了过来。同时,也贴了些其他的关于判断的代码。

李战代码
  1.         var Sys = {};
  2.         var ua = navigator.userAgent.toLowerCase();
  3.         var s;
  4.         (s = ua.match(/msie ([d.]+)/)) ? Sys.ie = s[1] :
  5.         (s = ua.match(/firefox/([d.]+)/)) ? Sys.firefox = s[1] :
  6.         (s = ua.match(/chrome/([d.]+)/)) ? Sys.chrome = s[1] :
  7.         (s = ua.match(/opera.([d.]+)/)) ? Sys.opera = s[1] :
  8.         (s = ua.match(/version/([d.]+).*safari/)) ? Sys.safari = s[1] : 0;
  9.  
  10.         //以下进行测试
  11.         if (Sys.ie) document.write('IE: ' + Sys.ie);
  12.         if (Sys.firefox) document.write('Firefox: ' + Sys.firefox);
  13.         if (Sys.chrome) document.write('Chrome: ' + Sys.chrome);
  14.         if (Sys.opera) document.write('Opera: ' + Sys.opera);
  15.         if (Sys.safari) document.write('Safari: ' + Sys.safari);

 以上的代码都是为了打造前端框架所做的预研,并在五大浏览器上测试通过。今后,判断某种浏览器只需用if(Sys.ie)或if(Sys.firefox)等形式,而判断浏览器版本只需用if(Sys.ie == '8.0')或if(Sys.firefox == '3.0')等形式,表达起来还是非常优雅的。

jquery
  1. var userAgent = navigator.userAgent.toLowerCase();
  2.  
  3. // Figure out what browser is being used
  4. jQuery.browser = {
  5.     version: (userAgent.match( /.+(?:rv|it|ra|ie)[/: ]([d.]+)/ ) || [0,'0'])[1],
  6.     safari: /webkit/.test( userAgent ),
  7.     opera: /opera/.test( userAgent ),
  8.     msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
  9.     mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
  10. };

jquery果然是精悍啊!下面看看yui的。

yui
  1. YAHOO.env.ua = function() {
  2.     var o={
  3.  
  4.         /**
  5.          * Internet Explorer version number or 0.  Example: 6
  6.          * @property ie
  7.          * @type float
  8.          */
  9.         ie:0,
  10.  
  11.         /**
  12.          * Opera version number or 0.  Example: 9.2
  13.          * @property opera
  14.          * @type float
  15.          */
  16.         opera:0,
  17.  
  18.         /**
  19.          * Gecko engine revision number.  Will evaluate to 1 if Gecko
  20.          * is detected but the revision could not be found. Other browsers
  21.          * will be 0.  Example: 1.8
  22.          * <pre>
  23.          * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
  24.          * Firefox 1.5.0.9: 1.8.0.9 <-- Reports 1.8
  25.          * Firefox 2.0.0.3: 1.8.1.3 <-- Reports 1.8
  26.          * Firefox 3 alpha: 1.9a4   <-- Reports 1.9
  27.          * </pre>
  28.          * @property gecko
  29.          * @type float
  30.          */
  31.         gecko:0,
  32.  
  33.         /**
  34.          * AppleWebKit version.  KHTML browsers that are not WebKit browsers
  35.          * will evaluate to 1, other browsers 0.  Example: 418.9.1
  36.          * <pre>
  37.          * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
  38.          *                                   latest available for Mac OSX 10.3.
  39.          * Safari 2.0.2:         416     <-- hasOwnProperty introduced
  40.          * Safari 2.0.4:         418     <-- preventDefault fixed
  41.          * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
  42.          *                                   different versions of webkit
  43.          * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
  44.          *                                   updated, but not updated
  45.          *                                   to the latest patch.
  46.          * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native SVG
  47.          *                                   and many major issues fixed).  
  48.          * 3.x yahoo.com, flickr:422     <-- Safari 3.x hacks the user agent
  49.          *                                   string when hitting yahoo.com and
  50.          *                                   flickr.com.
  51.          * Safari 3.0.4 (523.12):523.12  <-- First Tiger release - automatic update
  52.          *                                   from 2.x via the 10.4.11 OS patch
  53.          * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
  54.          *                                   yahoo.com user agent hack removed.
  55.          *                                  
  56.          * </pre>
  57.          * http://developer.apple.com/internet/safari/uamatrix.html
  58.          * @property webkit
  59.          * @type float
  60.          */
  61.         webkit: 0,
  62.  
  63.         /**
  64.          * The mobile property will be set to a string containing any relevant
  65.          * user agent information when a modern mobile browser is detected.
  66.          * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
  67.          * devices with the WebKit-based browser, and Opera Mini.  
  68.          * @property mobile
  69.          * @type string
  70.          */
  71.         mobile: null,
  72.  
  73.         /**
  74.          * Adobe AIR version number or 0.  Only populated if webkit is detected.
  75.          * Example: 1.0
  76.          * @property air
  77.          * @type float
  78.          */
  79.         air: 0,
  80.  
  81.         /**
  82.          * Google Caja version number or 0.
  83.          * @property caja
  84.          * @type float
  85.          */
  86.         caja: 0
  87.  
  88.     },
  89.  
  90.     ua = navigator.userAgent,
  91.    
  92.     m;
  93.  
  94.     // Modern KHTML browsers should qualify as Safari X-Grade
  95.     if ((/KHTML/).test(ua)) {
  96.         o.webkit=1;
  97.     }
  98.     // Modern WebKit browsers are at least X-Grade
  99.     m=ua.match(/AppleWebKit/([^s]*)/);
  100.     if (m&&m[1]) {
  101.         o.webkit=parseFloat(m[1]);
  102.  
  103.         // Mobile browser check
  104.         if (/ Mobile//.test(ua)) {
  105.             o.mobile = "Apple"; // iPhone or iPod Touch
  106.         } else {
  107.             m=ua.match(/NokiaN[^/]*/);
  108.             if (m) {
  109.                 o.mobile = m[0]; // Nokia N-series, ex: NokiaN95
  110.             }
  111.         }
  112.  
  113.         m=ua.match(/AdobeAIR/([^s]*)/);
  114.         if (m) {
  115.             o.air = m[0]; // Adobe AIR 1.0 or better
  116.         }
  117.  
  118.     }
  119.  
  120.     if (!o.webkit) { // not webkit
  121.         // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
  122.         m=ua.match(/Opera[s/]([^s]*)/);
  123.         if (m&&m[1]) {
  124.             o.opera=parseFloat(m[1]);
  125.             m=ua.match(/Opera Mini[^;]*/);
  126.             if (m) {
  127.                 o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
  128.             }
  129.         } else { // not opera or webkit
  130.             m=ua.match(/MSIEs([^;]*)/);
  131.             if (m&&m[1]) {
  132.                 o.ie=parseFloat(m[1]);
  133.             } else { // not opera, webkit, or ie
  134.                 m=ua.match(/Gecko/([^s]*)/);
  135.                 if (m) {
  136.                     o.gecko=1; // Gecko detected, look for revision
  137.                     m=ua.match(/rv:([^s)]*)/);
  138.                     if (m&&m[1]) {
  139.                         o.gecko=parseFloat(m[1]);
  140.                     }
  141.                 }
  142.             }
  143.         }
  144.     }
  145.  
  146.     m=ua.match(/Caja/([^s]*)/);
  147.     if (m&&m[1]) {
  148.         o.caja=parseFloat(m[1]);
  149.     }
  150.    
  151.     return o;
  152. }();

yui果然很好很强大,判断了N种~~~~~~~

最后来看看baidu自己的框架。bb就是b2b的意思吧。看看。

baidu BB框架
  1.     Browser: (function(){
  2.         var ua = window.navigator.userAgent.toLowerCase();
  3.         var b = {
  4.             platform: window.navigator.platform,
  5.             msie: /msie/.test(ua) && !/opera/.test(ua),
  6.             opera: /opera/.test(ua),
  7.             safari: /webkit/.test(ua) && !/chrome/.test(ua),
  8.             firefox: /firefox/.test(ua),
  9.             chrome: /chrome/.test(ua)
  10.         };
  11.         var vMark = "";
  12.         for (var i in b) {
  13.             if (b[i]) {
  14.                 vMark = i;
  15.             }
  16.         }
  17.         if (b.safari) {
  18.             vMark = "version";
  19.         }
  20.         b.version = (ua.match(eval("/(?:" + vMark + ")[\/: ]([\d.]+)/")) || [])[1];
  21.         b.ie = b.msie;
  22.         b.ie6 = b.msie && parseInt(b.version) == 6;
  23.         try {
  24.             b.maxthon = b.msie && !!external.max_version;
  25.         }
  26.         catch (e) {
  27.             b.maxthon = false;
  28.         }
  29.         return b;
  30.     })()

maxthon也判断了,基于external.max_version来判断。不过搜狗怎么判断呢?当IE7三。

有人说判断还是基于功能好,如同 if(window.XMLHttpRequest) ,但浏览器本来就在发展互相学习。难免功能交叉的时候。

下面是个很BT的判断IE 的东东。比短!

无敌短啊
  1. /*判断浏览器*/
  2. B=(function x(){})[-5]=='x'?'FF3':(function x(){})[-6]=='x'?'FF2':/a/[-1]=='a'?'FF':'v'=='v'?'IE':/a/.__proto__=='//'?'Saf':/s/.test(/a/.toString)?'Chr':/^function (/.test([].sort)?'Op':'Unknown'
  3.  
  4.  
  5. /*判断IE 好短!*/
  6. IE=top.execScript?1:0
  7.  
  8.  
  9. /*判断IE 更短!!!*/  
  10. IE='\v'=='v'

经测试能用。
!!!

 

  1. 1
  2. 2