作者: admin

  • JavaScript异步编程插件–jsDeferred.js

    JavaScript当前有众多实现异步编程的方式,最为耀眼的就是ECMAScript 6规范中的Promise对象,在ES6还没发布的时候一般都是用jquery提供的deferred对象,在《jquery Deferred对象 延迟对象》在有介绍,其实jquery中提供的队列函数也可以简单实现回调的功能《jQuery队列函数同步执行queue()、dequeue()、clearQueue()和.delay()》。在不久前介绍过另一个异步编程插件《js异步模块以及回调–async.js》。

    不管jquery的$.Deferred()和async.js他们都是解决了回调的问题,现在介绍另一款插件jsDeferred.js,其实它的思路和现在ES6添加的Promise对象思路是相似的,因为Promise/A+规范的制定基本上是奠定在jsDeferred上。

    官网:https://cho45.stfuawsc.com/jsdeferred/

    下面来介绍jsDeferred.js使用

     

    官网有几个版本,其中有一个是基于jquery下扩展的,如果你经常使用jquery的话推荐使用jquery版本的

    jsdeferred.jquery下载:jsdeferred.jquery

    目前测试兼容IE7以上浏览器(IE6没测试)

     

     

    如何调用

    <script type="text/javascript" src="jsdeferred.js"></script>
    <script>
    方式一:(个人喜欢这种方式)
    Deferred.define();
    next(function () {
       alert("Hello!");
    }).
    next(function () {
       alert("World!");
    });
    
    方式二:
    Deferred.next(function () {
      alert("Hello!");
    }).
    next(function () {
      alert("World!");
    });
    
    方式三:
    var d = new Deferred();
    
     d.next(function () {
       document.title=1;
     }).
     next(function () {
       document.title=2;
     });
    
     d.call();
    </script>
    自己选喜欢的方式用吧

     

    以后讲解案例就使用第一种方式说明

    next()队列执行,类似回调作用

    以往的写法内置回调嵌套
    http.get("/foo.json", function (dataOfFoo) {
      http.get("/bar.json", function (dataOfBar) {
         http.get("/baz.json", function (dataOfBaz) {
               alert([dataOfFoo, dataOfBar, dataOfBaz]);
         });
      });
    });
    
    
    next(function () {
     return http.get("/foo.json").next(function (data) {
        results.push(data);
     });
    }).
    next(function () {
     return http.get("/baz.json").next(function (data) {
        results.push(data);
     });
    }).
    next(function () {
     return http.get("/baz.json").next(function (data) {
        results.push(data);
     });
    }).
    next(function () {
      alert(results);
    });
    
    //next写法至少比第一种写法清晰多了

     

     数据传递

    next(function(){
      alert(1);
      return [1,2]  //只有reture才能把数据传递给下一个函数
    }).
    next(function(data){
      console.log(data);  //这里data就是获取到上一步return出来的数据[1,2]
    });

     

     parallel() 合并回调

    parallel(fn)、parallel([])、parallel({})  //支持3中格式

    parallel(
      function(){ return 1; },
      function(){ return 2; },
      function(){ return 3; }
    ).next(function(data){
      console.log(data);  //[1,2,3]
    });
    
    -----------------
    parallel([
      function(){ return 1; },
      function(){ return 2; },
      function(){ return 3; }
    ]).next(function(data){
     console.log(data); //[1,2,3]
    });
    
    --------------------
    parallel({
      foo: next(function () {
        return 1;
      }),
    
      bar: next(function () {
        return 2;
      })
    }).next(function (values) {
     console.log(values);// => Object { foo=1, bar=2 }
    });

     

    Error 出错回调

    我们写逻辑代码在进行判断时候如果满足条件就继续执行,如果不满足条件或者出错就执行错误的回调

    next(function () {
      console.log(0);
    }).
    next(function () {
      console.log(1);
      throw {err:'错了'};  //抛出错误
    }).
    next(function () {
      console.log(2);  //这步不会执行
    }).
    error(function (e) {
      console.log(e);  //{err:'错了'}  //处理错误的回调
    }).
    next(function () {  //继续执行
      console.log(3);
    });

     

    wait()时间延迟加载

    next(function () {
      console.log(0);
      return wait(5);  //5秒后才继续执行下一步
    }).
    next(function () {
      console.log(1);
    })

     

    嵌套

     next(function () {
        alert(1);   //第一步
        return next(function () {
                  alert(2);  //第二步
               }).
               next(function () {
                  alert(3);  //第三步
               });
    }).
    next(function () {
         alert(4);   //第四步
    });
    
    如果没有 return
    
    next(function () {
       alert(1); //第一步
       next(function () {
                    alert(2); //第三步
              }).
              next(function () {
                    alert(3); //第四步
              });
       }).
    next(function () {
     alert(4); //第二步
    });
    
    

     

    loop()循环  类似for循环

    loop(1000, function (n) {  //n索引从0开始
       // heavy process
    });

     

     call()  //可以理解为一个jsDeferred内置提供的执行函数吧!,直接上案例不太好说明

    next(function () {
      function pow (x, n) { //定义了pow函数但是没执行
         return x+n;
      }
      return call(pow, 2, 10);  // (要执行的函数,带入的参数1,带入的参数2)
    }).
    next(function (n) {
      console.log(n); //12
    });
    
    
    
    call(function (text) {
       console.log(text);//=> linkFly
    }, 'linkFly');
    console.log('hello,world!');// => 先输出

     

    判断某实例化的对象是否为jsDeferred内置的

    var obj =new wo();
    
    Deferred.define();
     console.log(Deferred.isDeferred(obj));//=> false
     console.log(Deferred.isDeferred(wait(2)));//=> true

     

    还有更多方法可以参考官网或者以下网站

     中文参考:http://www.guudo.cn/tech/view/id/8359

  • 谷歌浏览器firebug控制台的一个细节

    <div id="wo">11</div>  //创建一个元素
    
    console.log( document.getElementById('wo') );  //查看元素

    当我们到控制台查看结果时不停的刷新就会有两种不同的结果

    第一种:显示出了很多属性和方法

    firebug1

     

    第二种:只显示DOM元素

    firebug2

     

    上面两种结果都正确,第二种结果仅仅显示我们需要看的DOM元素而已,但是第一种不仅显示DOM结果,还显示原生DOM能支持多少原生JS 的属性和方法列举了很详细,例如:

    // innerHTML是DOM其中一种JS内置提供的属性功能
    document.getElementById('wo').innerHTML
  • 图解:RequireJS异步加载原理,了解它是怎么工作的

    201571114812111

    图中,第一种方式就是我们平时使用的方式,按顺序的加载JS的依赖模块,但是一旦出现了阻塞后面的JS就不会加载了。

    AMD的加载方式就如图中,第二种方式,在加载JS模块时是异步的并不需要等待其他模块完全加载完后才去加载,并且在模块依赖加载的时候又按照着一定的顺序加载,保证依赖其他模块的模块能够正常运行。

    http://www.jb51.net/article/68726.htm

     

  • JavaScript对象的property属性详解

    JavaScript中对象的property有三个属性:
    1.writable。该property是否可写。
    2.enumerable。当使用for/in语句时,该property是否会被枚举。
    3.configurable。该property的属性是否可以修改,property是否可以删除。

    在ECMAScript 3标准中,上面三个属性的值均为true且不可改:新建对象的property是可写的、可被枚举的、可删除的;而在ECMAScript 5标准中,可通过property的描述对象(property descriptor)来对这些属性进行配置和修改。

    var obj = {};
    
    Object.defineProperty(obj, 'name', {
        configurable: true, //允许删除name属性名,delete obj.name
        writable: true, //允许修改
        enumerable: true, //允许枚举 fon...in
        value: '张三'
    });
    
    
    Object.defineProperty(obj, 'age', {
        configurable: false, //不允许删除
        writable: false, //不允许修改
        enumerable: false, //不允许枚举
        value:18
    });
    
    // {name: "张三", age: 18}
    
    
    --------------------------
    或者
    --------------------------
    var obj = {};
    var xx;
    
    
    Object.defineProperty(obj, 'age', {
        configurable: true, 
        enumerable: true, 
        get : function(){
            return xx  //这里为age属性赋值
        },
        set:function (v) {
            xx=v;   
        },
    });
    
    obj.age=29
    
    
    console.log(JSON.stringify(obj));
    console.log(xx);  // 29
    先执行set函数在执行get函数

     

     

    如果将property的值信息也作为property的属性来看的话,对象中的property拥有四个属性:value、writable、enumerable和configurable。

    对于用getter和setter方法来定义的property,由于其没有writable属性(property是否可写取决于setter方法是否存在),因此这种property也有四个属性:get、set、enumerable和configurable — get和set属性的值为function。

    获取对象property的属性

    ECMAScript 5标准中,可以通过Object.getOwnPropertyDescriptor()来获取对象自身某个property的属性信息:

    复制代码代码如下:
    var o = {x:1};
    var a = Object.create(o);
    a.y = 3;
    console.log(Object.getOwnPropertyDescriptor(a, “y”));//Object {configurable=true, enumerable=true, writable=true, value=3}
    console.log(Object.getOwnPropertyDescriptor(a, “x”));//undefined


    可以看到,如果property不存在或者property继承自原型对象,则返回undefined。

    设置对象property的属性

    ECMAScript 5标准中,可以通过Object.defineProperty()来设置对象自身某个property的属性:

    复制代码代码如下:
    Object.defineProperty(a, “y”, {
    value:3,
    writable:true,
    enumerable:false,
    configuration:true
    });
    console.log(a.propertyIsEnumerable(“y”));//false


    如果设置的property是从原型对象中继承而来的,那么JavaScript将在对象自身中创建一个同名的property,这与赋值操作的相关行为一致:

    复制代码代码如下:
    Object.defineProperty(a, “x”, {
    value:1,
    writable:true,
    enumerable:false,
    configuration:true
    });
    console.log(a.propertyIsEnumerable(“x”));//false
    console.log(o.propertyIsEnumerable(“x”));//true


    除了修改property的属性,还可以将property改为用getter或setter访问:

    复制代码代码如下:
    Object.defineProperty(a, “y”, {
    get:function(){return 42;}
    });
    console.log(a.y);//42


    在使用Object.defineProperty()时,property描述对象中的属性值可以部分忽略,当属性值有所忽略时,JavaScript中的处理规则如下:

    如果property是新建的,则所有忽略的属性值均为false或undefined。
    如果property已存在,则所有忽略的属性值维持原样不变。

    批量设置对象property的属性

    如果需要一次性设置多个property的属性,可以使用Object.defineProperties()语句。该语句将返回修改后的对象。

    复制代码代码如下:
    Object.defineProperties(a, {
    “y”:{value:79, writable:true, enumerable:true, configurable:true},
    “z”:{value:99, writable:true, enumerable:true, configurable:true}
    });
    console.log(a);//Object {y=79, z=99}


    property属性设置规则

    当对property属性进行修改时,必须遵循以下规则。如果违反规则,JavaScript将报TypeError错误:

    如果对象不是extensible的,则只能修改已有property的属性,无法添加新的property。
    如果property的configurable属性为false,则无法修改configurable和enumerable属性的值,对于writable属性,可以将其从true改为false,但无法将其从false改为true。如果property由getter和setter定义,则getter和setter方法无法被修改。
    如果property的configurable属性和writable属性均为false,则property值不可改。如果property的writable属性为false,但其configurable属性为true,则property值依然可以修改。

  • avalon.js原理以及Object.defineProperty

    avalon.js是基于Object.defineProperty实现的双向数据绑定的,但是对于IE6/7/8浏览器的不兼容就使用VBscript做兼容处理,这里就不考虑VB了,来介绍下Object.defineProperty封装属性访问器。

    Object.defineProperty(obj, prop, descriptor)  //待修改的对象,带修改的属性名称,待修改属性的相关描述

    例子:

    var obj={};
    
    Object.defineProperty(obj, "name", {  //作用对象是obj,设置name属性(可能是修改或者添加属性名)
      value:undefined, //属性的默认值
      writable:false, //属性是否可重写。可重写的含义包括:是否可以对属性进行重新赋值
      enumerable:false, //属性是否可枚举。可枚举的含义包括:是否可以通过 for...in 遍历到,是否可以通过 Object.keys() 方法获取属性名称。
      configuration:false, //属性是否可配置。可配置的含义包括:是否可以删除属性( delete ),是否可以修改属性的 writable 、 enumerable 、 configurable 属性
      set:function(){ 
          //属性的重写器(暂且这么叫)。一旦属性被重新赋值,此方法被自动调用
      },
      get:function(){
          //属性的读取器(暂且这么叫)。一旦属性被访问读取,此方法被自动调用
      }
    });
    
    注意:某个属性设置了 writable 或者 value 属性,那么这个属性就不能声明 get 和 set 了,反之亦然。

    原作者地址还简单介绍了其他mvvm的实现原理感谢蛋糕仙人: http://blog.gejiawen.com/2015/04/02/2-way-data-binding-and-define-property/

     

    更多的Object.defineProperty参数中的descriptor介绍:

    http://www.jb51.net/article/48594.htm

    https://sdeno.com/?p=5007

     

    MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty