博客

  • SVG 与 Canvas:如何选择

    通过最新浏览器中提供的现有矢量图形技术的分析功能,可以交互方式使用标准 Web 技术来满足现有的和新的方案。 从今以后,我们将拥有巨大的机会可以让声明性动画支持广告版位。 通过使用方案驱动的功能开发,我们可以在竞争中处于领先地位,并在 Web 应用程序和网页中提供基于标准的图形丰富的体验。

    http://msdn.microsoft.com/zh-cn/library/gg193983

  • 构造函数、原型函数和原型链的关系

    案例:Untitled-1

    首先看下构造函数的一个简单例子:

    var Box=function(){ //声明一个类
    this.name=’我’;
    this.age=25;
    this.run=function(){
    return this.name+this.age;
    }
    }

    var box1 =new Wo(); //类实例化成对象
    var box2 =new Wo();
    alert(p1.run());
    以上声明类的方式就叫做构造函数,这样的属性和方法就是实例属性和实例方法。
    同时new了两个实例化对象box1和box2 它们的实例属性方法地址都是独立的如图:

    func1

     

    但是new多个实例对象会造成资源的浪费所以需要公用一个地址,这时我们需要原型函数。

    var Box=function(){ //声明一个类
    this.prototype.name=’我’;
    this.prototype.age=25;
    this.prototype.run=function(){
    return this.name+this.age;
    }
    }

    var box1 =new Wo(); //类实例化成对象
    var box2 =new Wo();
    alert(p1.run());
    原型函数只需要加prototype,以上的属性和方法就是原型属性和原型方法,地址是共享的,如图:

     

    func2

     

    没有定义实例属性和方法所以是空的。

    注意如果原型用字面量的方式写第二次的话,之前写的字面量原型关系就会被中断。例如
    Box.prototype={ name:’我’,age:18 };
    Box.prototype={ sex:’男’}; //重写了第二次,之前写的Box原型不会被继承。

     

    我们每创建一个(构造)函数的时候就默认存在一个prototype对象,这个对象是用来存储共享的属性和方法,不存在__proto__。如果创建一个实例函数默认才会有__proto__,这个是隐藏的原型链接始终指向原型函数即使搞乱p1.constructor=’asdf’也依然能正常去获取到原型函数里的属性和方法,实例函数不存在prototype属性,但是实例函数可以通过__proto__指向prototype属性去寻找我们需要的属性和方法,所以说:__proto__存在于实例函数与原型函数之间。

    上面说了每创建一个(构造)函数的时候默认存在一个prototype属性,prototype属性默认获取constructor属性,这个属性又会指向所创建的构造函数。

    console.log(p1.constructor.prototype.ceshi === p1.ceshi); //完全等价

     

     

    对于说到原型函数所以就要涉及到原型链,在图中我们可以看到__proto__,只要是new出现一个实例对象就会有__proto__,__proto__也就会自动指向prototype寻找prototype里面的原型属性和方法。

    简单说下面向对象的工作流程:
    1,声明一个类时,里面可以添加方法和属性。
    2,实例化对象需要new,当new的时候JS就默认创建了一个__proto__属性,这个是JS内置的需要寻找原型函数用的。
    3,当我们要调用面向对象里面的属性或者方法时,先通过__proto__一层层的寻找需要的实例属性和方法,如果找到了就不会在去找原型的了,如果找不到__proto__最终到prototype里面寻找原型属性和方法,所以说:每个实例对象里面的__proto__属性指向的是原型函数,实例对象跟new它们之前的构造函数没什么直接关系。

    原型链的核心就是__proto__。

    __proto__最终指向的是原型prototype。例如在类中创建了一个原型方法,我们可以通过这样的方法调用。

    p1.__proto__.run(); //调用原型的run方法

    p1.__proto__.run=function(){}   //这样也相当于在原型中创建了方法,因为__proto__直接指向原型。

    prototype_pic

    g_h_h

    上图中prototype重复写了好几次,其实也可以用字面量方式写:

    Wo.prototype={
      name:'',
      age:''
      run:function(){}
    }
    字面量的方式写效果跟之前的一样,但是唯一不同的是Wo构造函数里面的prototype属性指向的原型对象里面的constructor属性不再是指向Wo构造函数了,如果需要重新指向Wo构造函数只需要添加一个属性即可:
    Wo.prototype={
     constructor:Wo,
     name:'',
     age:''
     run:function(){}
    }
    (实际上我也不知道constructor具体有什么用?_?)

     

    关于构造函数和原型对象的this

     function Wo() {
         console.log(this);  //这里的this 指的是new Wo()实例化后的对象
         this.name="chen";  //对外变量
         var xx="xx";   //私有变量
     }
     
     Wo.prototype.say=function () {
         console.log( this.name );  // chen
         console.log( this.xx );  //undefined
         console.log( this ); //这里的this 指的是new Wo()实例化后的对象
     }
    
     new Wo().say();

     

     

    推荐使用组合:

     function Baba(name) {
         this.baba_name=name;
         this.color=['red','greent'];
     }
    
    
     Baba.prototype.sayname=function () {
         return this.baba_name; //当构造函数被new时,原型对象里面this指的是构造函数
     };
    
    
    
     function Son(name,age) {
         Baba.call(this,name);
         this.age=age;
     }
    
    
     Son.prototype=new Baba();
     Son.prototype.constructor=Son;
     Son.prototype.sayage=function () {
         console.log(this.age);
     };
    
    
     var p1=new Son('chen',22);
     var p2=new Son('ge',29);
    
     //son的构造函数和原型对象中都没有sayname方法,但是son的原型对象继承了new Baba(),
     //而Baba构造函数中的原型对象又有sayname函数,所以p1和p2共享着其实是Baba构造函数的原型对象里面的sayname函数
    console.log(p1.sayname()) ;  //chen
    console.log(p2.sayname()) ;  //ge
    
    
    //会有人问Son.prototype=new Baba()不是继承了Baba构造函数里面的所有属性和方法了吗?所以color应该也是共享的啊?
    // 没错,但是别忘记了son之前还Baba.call(this,name); 也就是说son构造函数里面已经有了color对象了,
    // 所以就不必去son的prototype里面去找color对象了。所以修改color对象是独立私有的
    p1.color.push('pink');
    console.log(p1.color);  // ['red','greent','pink']
    console.log(p2.color);  // ['red','greent']

     

     

    fun1

    Js中Prototype、__proto__、Constructor、Object、Function关系介绍

    《请问js中给function添加的属性去哪儿了?有什么用途?》

  • js作用域探讨

    var a = "hello";
     b = "world";
    
    Test();
    
    function Test() {
      alert(a + " " + b);
      var a = "welcome";
      b = "china";
      alert(a + " " + b);
    }
    
    alert(a + " " + b);
    
    解析:
    
    
    var a = "hello";
     b = "world";
    
    Test();
    
    function Test() {
     var a=undefined; //因为函数里面有 var a关键词所以在函数的前面就会初始值为undefined
     alert(a + " " + b);  //a找到的是上面的undefined  ,b找到的是function外面的world
     var a = "welcome";
     b = "china";
     alert(a + " " + b);  //a找到的是函数里面的welcome  ,b找到的是函数里面的china
    }
    
    alert(a + " " + b); //a找的是全局的hello,函数里面的a是局部的找不到,b找的是china已经被函数中的 b = "china"给覆盖了这是声明全局变量
    
    
     当函数里面有变量不管是声明在最前还是最后一旦有var都会先为变量赋值一个undefined,定义在最前面。
     如果函数里面没有找到var的变量就会跑到函数外去寻找对应的。

    这段代码分别输出的结果是:undefined world,welcome china, hello china.

    http://kb.cnblogs.com/page/55178/

  • jquery封装插件

    jquery插件 开发插件

    jquery封装的插件,是为了日后调用起来方便,只需要输入参数即可实现我们需要的效果。
    jquery为我们提供了$.extend和$.fn.extend的方法,一个是全局封装一个是局部封装,

    $.extend为jQuery类添加类方法

    $.fn.extend是对jQuery.prototype进得扩展,就是为jQuery类添加“成员函数”,我们基本也这么写

     

     

    // 1,第一个参数不写布尔值,默认是false浅拷贝,意思就是对象里面还有对象的话,那么就以最后一个覆盖前面一个https://sdeno.com/?p=3055
    // 2,如果有2个对象的话,2个对象会进行合并,至于深拷贝还是浅拷贝看第一个参数的设置。
    // 3,如果就一个对象的话,则会根据你使用的是$.extend还是$.fn.extend,进行jQuery类的扩展,还是为jQuery添加成员”属性和方法了,一般为jQuery扩展插件也是以这样的方法,也就是只传入一个对象,则就会把jQuery当作目标和传入的对象合并。

    $.extend(false,{},{},{},…);

     

    不管$.fn.extend还是$.extend,如果里面的参数只有一个对象的话,那么目标对象就会是jQuery.fn或者jQuery。参数对象就会被合并到jQuery中。所以我们常用这种方式去扩展jQuery插件。

    例如:

    ;(function($){
       $.fn.extend({
          'color':function(value1,value2){
           $(this).css({'color':value1,'background':value2});
       }
     });
     })(jQuery);
     调用只需要:
     $('div').color('red','yellow');
    还有另一种调用方式:$('#wo').color({fc:'#000',bg:'yellow'},function(){ //回调 });
    ;(function($){
        $.fn.extend({
     
            'color':function(opt,fn){ //opt 新值
                 var oldvalue={//默认值
                    bg:'yellow',
                    fc:'pink',
                    bor:'1px solid red'
                 } 
    
                 var resule=$.extend({},oldvalue,opt||{});//设置新信就会覆盖久值,没有设置就使用默认值
                 var _this=$(this);
    -----------------------------------------------------------------------------------------------以下是完成回调部分代码
                 var wait = function(dtd){
                 var dtd = $.Deferred(); //在函数内部,新建一个Deferred对象
                 var tasks = function(){
                   _this.css({'color':resule.fc,'background':resule.bg,'border':resule.bor});
                  dtd.resolve(); // 修改$.Deferred()状态为成功
                 };
                 tasks();
                 return dtd.promise(); // 返回promise对象,防止外面随意修改$.Deferred()状态
                 };
    
                 $.when(wait())
                 .  done(function(){ 
                        if(typeof fn == 'function'){
                            fn();
                      }
                  }) //成功之后的回
    ------------------------------------------------------------------------------------------------------
              }//color
     
        })
    })(jQuery);
    
    案例下载:http://pan.baidu.com/s/1bntuZi3

     

    还有另一种封装代码的形式:

    (function($) { 
        $.fn.watch = function(callback) { 
              return $(this).each(function() { 
             //缓存以前的值 
            $.data(this, 'originVal', $(this).val()); //代码初始化先执行了这里
     
            //event 
           $(this).on('keyup paste', function() { 
                  var originVal = $.data(this, 'originVal'); 
                 var currentVal = $(this).val(); 
                console.log('之前值:'+originVal);
                console.log('现在值:'+currentVal);
     
     
               if (originVal !== currentVal) { 
                   $.data(this, 'originVal', $(this).val()); 
                   callback(currentVal); 
               } 
           }); 
       }); 
     } 
    })(jQuery);

     

    调用:
    $(function(){
      $(".tx").watch(function(value) { 
          document.title=value;
      });
    });

    两种代码封装效果都是一样的,我跟人比较倾向于第一种。

     

     

     

    以上是局部封装,全局封装只需要修改成$.extend即可。

    封装在$.extend里面如果调用就使用

    extend1

    调用:

    $.liu()  //这样就能调用,类似$.ajax();

    为jQuery类添加添加类方法,可以理解为添加静态方法。如:
    $.extend({ 
       add:function(a,b){return a+b;} 
    }); 
    便为 jQuery 添加一个为 add 的 “静态方法”,之后便可以在引入 jQuery 的地方,使用这个方法了,$.add(3,4); //return 7

    http://jingyan.baidu.com/article/fec4bce259ef67f2608d8b10.html

    jquery_fz

     

    ——————————————————————————————————-

    http://www.cnblogs.com/RascallySnake/archive/2010/05/07/1729563.html

    jQuery.extend 函数详解

    JQuery的extend扩展方法:
    Jquery的扩展方法extend是我们在写插件的过程中常用的方法,该方法有一些重载原型,在此,我们一起去了解了解。
     一、Jquery的扩展方法原型是:

    extend(dest,src1,src2,src3…);

    它的含义是将src1,src2,src3…合并到dest中,返回值为合并后的dest,由此可以看出该方法合并后,是修改了dest的结构的。如果想要得到合并的结果却又不想修改dest的结构,可以如下使用:

    var newSrc=$.extend({},src1,src2,src3…)//也就是将”{}”作为dest参数。

    这样就可以将src1,src2,src3…进行合并,然后将合并结果返回给newSrc了。如下例:

    var result=$.extend({},{name:Tom,age:21},{name:Jerry,sex:Boy})

     

    那么合并后的结果

    result={name:Jerry,age:21,sex:Boy}

    也就是说后面的参数如果和前面的参数存在相同的名称,那么后面的会覆盖前面的参数值。

    二、省略dest参数
    上述的extend方法原型中的dest参数是可以省略的,如果省略了,则该方法就只能有一个src参数,而且是将该src合并到调用extend方法的对象中去,如:
    1、$.extend(src)
       该方法就是将src合并到jquery的全局对象中去,如:

    $.extend({
    hello:function(){alert(
    hello);}
    });

    就是将hello方法合并到jquery的全局对象中。
    2、$.fn.extend(src)
    该方法将src合并到jquery的实例对象中去,如:

    $.fn.extend({
    hello:function(){alert(
    hello);}
    });

     

    就是将hello方法合并到jquery的实例对象中。

    下面例举几个常用的扩展实例:

    $.extend({net:{}});

     

    这是在jquery全局对象中扩展一个net命名空间。

    $.extend($.net,{
    hello:function(){alert(
    hello);}
    })

    这是将hello方法扩展到之前扩展的Jquery的net命名空间中去。

    三、Jquery的extend方法还有一个重载原型:

    extend(boolean,dest,src1,src2,src3…)

    第一个参数boolean代表是否进行深度拷贝,其余参数和前面介绍的一致,什么叫深层拷贝,我们看一个例子:

    var result=$.extend( true, {},
    { name:
    John, location: {city: Boston,county:USA} },
    { last:
    Resig, location: {state: MA,county:China} } );

    我们可以看出src1中嵌套子对象location:{city:”Boston”},src2中也嵌套子对象location:{state:”MA”},第一个深度拷贝参数为true,那么合并后的结果就是:

    result={name:John,last:Resig,
    location:{city:
    Boston,state:MA,county:China}}

     

    也就是说它会将src中的嵌套子对象也进行合并,而如果第一个参数boolean为false,我们看看合并的结果是什么,如下:

    var result=$.extend( false, {},
    { name:
    John, location:{city: Boston,county:USA} },
    { last:
    Resig, location: {state: MA,county:China} }
    );

    那么合并后的结果就是:

    result={name:John,last:Resig,location:{state:MA,county:China}}

     

     

    $.extend(true,a,b)

    true // a继承了b的属性和方法,如果在a中修改属性的话也会修改到了b,为了不受影响改true。

    false // 默认参数,a继承了b的属性和方法,如果在a中修改属性的话也会修改到了b

    以上就是$.extend()在项目中经常会使用到的一些细节。

     

    对extend的一些认识:要配合jQuery原生代码理解

    《jQuery.extend和jQuery.fn.extend区别》

     

  • [菜单导航] 下拉滚动自动隐藏上拉滚动自动显示导航插件Headroom.js

    [菜单导航] 下拉滚动自动隐藏上拉滚动自动显示导航插件Headroom.js,此效果用于手机客户端是个不错滴选择。

    http://wicky.nillia.ms/headroom.js/

    headroom.min