您的位置:奥门新浦京网址 > Wed前段 > 到底是干什么的,创建对象的

到底是干什么的,创建对象的

发布时间:2019-11-06 14:11编辑:Wed前段浏览(112)

    JS 的 new 到底是干什么的?

    2017/04/10 · JavaScript · 4 评论 · new

    原文出处: 方应杭   

    大部分讲 new 的文章会从面向对象的思路讲起,但是我始终认为,在解释一个事物的时候,不应该引入另一个更复杂的事物。

    今天我从「省代码」的角度来讲 new。

    —————————

    想象我们在制作一个策略类战争游戏,玩家可以操作一堆士兵攻击敌方。

    我们着重来研究一下这个游戏里面的「制造士兵」环节。

    一个士兵的在计算机里就是一堆属性,如下图:

    图片 1

    我们只需要这样就可以制造一个士兵:

    JavaScript

    var 士兵 = { ID: 1, // 用于区分每个士兵 兵种:"美国大兵", 攻击力:5, 生命值:42, 行走:function(){ /*走俩步的代码*/}, 奔跑:function(){ /*狂奔的代码*/ }, 死亡:function(){ /*Go die*/ }, 攻击:function(){ /*糊他熊脸*/ }, 防御:function(){ /*护脸*/ } } 兵营.制造(士兵)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var 士兵 = {
      ID: 1, // 用于区分每个士兵
      兵种:"美国大兵",
      攻击力:5,
      生命值:42,
      行走:function(){ /*走俩步的代码*/},
      奔跑:function(){ /*狂奔的代码*/  },
      死亡:function(){ /*Go die*/    },
      攻击:function(){ /*糊他熊脸*/   },
      防御:function(){ /*护脸*/       }
    }
     
    兵营.制造(士兵)

    浅谈 JS 创建对象的 8 种模式

    2015/10/16 · JavaScript · 对象

    原文出处: Tomson   

    • Objct 模式
    • 工厂模式
    • 构造器模式
    • 通过 Function 对象实现
    • prototype 模式
    • 构造器与原型方式的混合模式
    • 动态原型模式
    • 混合工厂模式

    H5 Crash 研究

    2016/05/31 · HTML5 · Crash

    原文出处: 小胡子哥(@Barret李靖)   

    我们知道,支撑页面在 webview 上良好运转的前提是具备一个高效并且稳定的 webview 容器,而容器的高效稳定不仅仅由容器提供方来保障,也需要容器使用者遵守一些基本准则,否则就有可能出现页面 Crash 的情况,这些准则是什么?什么样的上层代码会引起容器异常退出?这是本文需要阐述的内容。

    制造一百个士兵

    如果需要制造 100 个士兵怎么办呢?

    循环 100 次吧:

    JavaScript

    var 士兵们 = [] var 士兵 for(var i=0; i<100; i++){ 士兵 = { ID: i, // ID 不能重复 兵种:"美国大兵", 攻击力:5, 生命值:42, 行走:function(){ /*走俩步的代码*/}, 奔跑:function(){ /*狂奔的代码*/ }, 死亡:function(){ /*Go die*/ }, 攻击:function(){ /*糊他熊脸*/ }, 防御:function(){ /*护脸*/ } } 士兵们.push(士兵) } 兵营.批量制造(士兵们)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    var 士兵们 = []
    var 士兵
    for(var i=0; i<100; i++){
      士兵 = {
        ID: i, // ID 不能重复
        兵种:"美国大兵",
        攻击力:5,
        生命值:42,
        行走:function(){ /*走俩步的代码*/},
        奔跑:function(){ /*狂奔的代码*/  },
        死亡:function(){ /*Go die*/    },
        攻击:function(){ /*糊他熊脸*/   },
        防御:function(){ /*护脸*/       }
      }
      士兵们.push(士兵)
    }
     
    兵营.批量制造(士兵们)

    哎呀好简单。

    1.Object 模式

    JavaScript

    var o1 = {};//字面量的表现形式 var o2 = new Object; var o3 = new Object(); var o4 = new Object(null); var o5 = new Object(undefined); var o6 = Object.create(Object.prototype);//等价于 var o = {};//即以 Object.prototype 对象为一个原型模板,新建一个以这个原型模板为原型的对象 //区别 var o7 = Object.create(null);//创建一个原型为 null 的对象

    1
    2
    3
    4
    5
    6
    7
    8
    var o1 = {};//字面量的表现形式
    var o2 = new Object;
    var o3 = new Object();
    var o4 = new Object(null);
    var o5 = new Object(undefined);
    var o6 = Object.create(Object.prototype);//等价于 var o = {};//即以 Object.prototype 对象为一个原型模板,新建一个以这个原型模板为原型的对象
    //区别
    var o7 = Object.create(null);//创建一个原型为 null 的对象

    在 chrome 里查看各个新建对象的区别:
    图片 2

    可以看出前6种模式创建出来的对象都是一样的,第七种不同点在于其虽然也为 Object 对象但其无任何属性(包括没有任何可以继承的属性,因为创建的时候没有指定其原型)

    H5 Crash 问题概况

    下图是 H5 Crash 的大致流程图:

    图片 3

    由于前端没办法捕捉到页面 Crash 的状态和堆栈,但是 H5 页面上发生的错误会传递到 Java 和更底层的 Native 直到容器异常退出,在退出的那一刻,容器会将堆栈写入到日志中,当下次打开容器时(也可能是定时上报)就会上报这些堆栈信息。

    质疑

    上面的代码存在一个问题:浪费了很多内存。

    1. 行走、奔跑、死亡、攻击、防御这五个动作对于每个士兵其实是一样的,只需要各自引用同一个函数就可以了,没必要重复创建 100 个行走、100个奔跑……
    2. 这些士兵的兵种和攻击力都是一样的,没必要创建 100 次。
    3. 只有 ID 和生命值需要创建 100 次,因为每个士兵有自己的 ID 和生命值。

    2.工厂模式

    JavaScript

    //工厂方法1 通过一个方法来创建对象 利用 arguments 对象获取参数设置属性(参数不直观,容易出现问题) function createCar(){ var oTemp = new Object(); oTemp.name = arguments[0];//直接给对象添加属性,每个对象都有直接的属性 oTemp.age = arguments[1]; oTemp.showName = function () { alert(this.name); };//每个对象都有一个 showName 方法版本 return oTemp; } createCar("tom").showName();//在 JS 中没有传递的实参,实际形参值为 undefined(这里的 age 为 undefined) createCar("tim",80).showName(); alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //工厂方法1 通过一个方法来创建对象 利用 arguments 对象获取参数设置属性(参数不直观,容易出现问题)
    function createCar(){
        var oTemp = new Object();
        oTemp.name = arguments[0];//直接给对象添加属性,每个对象都有直接的属性
        oTemp.age = arguments[1];
        oTemp.showName = function () {
            alert(this.name);
        };//每个对象都有一个 showName 方法版本
        return oTemp;
    }
    createCar("tom").showName();//在 JS 中没有传递的实参,实际形参值为 undefined(这里的 age 为 undefined)
    createCar("tim",80).showName();
    alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类

    JavaScript

    //工厂方法2 通过传参设置属性(参数直观明了) function createCar(name,age){ var oTemp = new Object(); oTemp.name = name;//直接给对象添加属性,每个对象都有直接的属性 oTemp.age = age; oTemp.showName = function () { alert(this.name); };//每个对象都有一个 showName 方法版本 return oTemp; } createCar("tom").showName(); createCar("tim",80).showName(); alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //工厂方法2 通过传参设置属性(参数直观明了)
    function createCar(name,age){
        var oTemp = new Object();
        oTemp.name = name;//直接给对象添加属性,每个对象都有直接的属性
        oTemp.age = age;
        oTemp.showName = function () {
            alert(this.name);
        };//每个对象都有一个 showName 方法版本
        return oTemp;
    }
    createCar("tom").showName();
    createCar("tim",80).showName();
    alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类

    H5 Crash 原因初探

    测试代码 仓库地址:

    git clone ; cd demo;

    1
    2
    git clone https://github.com/barretlee/h5crash.git;
    cd demo;

    注意: 代码需要在 Webview 容器中测试,PC 浏览器下不会出现异常。

    H5 Crash 的原因不太明显,但是从经验上判断和摸索,大致归类为以下三种:

    1. 内存问题

    • 测试方法:使用闭包,不断增加内存量,看看增加到哪个区间大小, webview 容器会出现异常
    • 测试地址:(微信、微博或者其他客户端打开该页面的用户,可以点进去测试下,选择 100M 内存,不出意外,你的客户端会闪退。)

    XHTML

    <script> var Closure = function() { var _cache = []; var cache = 0; var add = function(size) { cache += size; size = size * 1024 * 1024; _cache.push(new Array(size).join('x')); refresh(); }; var refresh = function() { r.innerHTML = '内存消耗: ' + cache + 'M'; }; return { cache: cache + 'M', add: add, refresh: refresh } }; var closure = Closure(); </script> <button onclick="closure.add(1)">增加 1M 内存消耗</button> <button onclick="closure.add(10)">增加 10M 内存消耗</button> <button onclick="closure.add(20)">增加 20M 内存消耗</button> <button onclick="closure.add(50)">增加 50M 内存消耗</button> <button onclick="closure.add(100)">增加 100M 内存消耗</button> <div id="r">内存消耗:0 M</div>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    <script>
    var Closure = function() {
      var _cache = [];
      var cache = 0;
      var add = function(size) {
        cache += size;
        size = size * 1024 * 1024;
        _cache.push(new Array(size).join('x'));
        refresh();
      };
      var refresh = function() {
        r.innerHTML = '内存消耗: ' + cache + 'M';
      };
      return {
        cache: cache + 'M',
        add: add,
        refresh: refresh
      }
    };
    var closure = Closure();
    </script>
     
    <button onclick="closure.add(1)">增加 1M 内存消耗</button>
    <button onclick="closure.add(10)">增加 10M 内存消耗</button>
    <button onclick="closure.add(20)">增加 20M 内存消耗</button>
    <button onclick="closure.add(50)">增加 50M 内存消耗</button>
    <button onclick="closure.add(100)">增加 100M 内存消耗</button>
     
    <div id="r">内存消耗:0 M</div>

    存在的干扰:这种测试存在比较多的干扰,比如设备类型、系统类型(iOS/Android)、和设备内存运行状态等。

    2. Layers 数问题

    Layers 数的获取比较麻烦,Chrome Driver 没有提供该数据的接口,目前也没有比较好的办法拿到这个数据。

    • 测试方法:通过不同的方式创建层,观察页面的 Crash 情况
    • 测试地址:

    XHTML

    <style>.transform { transform: translateZ(0); } .animation { width:100px; height:100px; background:red; position:relative; animation:move 5s infinite; } @keyframes move { from {left:0px;} to {left:200px;} } </style> <script> var Layer = function() { function getType() { return document.querySelector('input:checked').value; }; return { createOne: function(index) { var div = document.createElement('div'); div.appendChild(document.createTextNode(index)); switch(getType()) { case 'opacity': div.style.cssText = "opacity:" + (index / 1000); break; case 'transform': div.className = 'transform'; break; case 'animation': div.className = 'animation'; break; case 'zindex': div.style.cssText = "position:relative; z-index:" + index; break; } document.body.appendChild(div); }, create: function(num) { [].slice.call(document.querySelectorAll('div')).forEach(function(item) { item.parentNode && item.parentNode.removeChild(item); }); while(num--) { this.createOne(num); } } } }; var layer = Layer(); </script> <strong>层类型: </strong> <ul> <li><label><input type="radio" checked name="type" value="opacity"> <span>通过 opacity 创建层</span></label></li> <li><label><input type="radio" name="type" value="transform"> <span>通过 transforms 创建层</span></label></li> <li><label><input type="radio" name="type" value="animation"> <span>通过 animation 创建层</span></label></li> <li><label><input type="radio" name="type" value="zindex"> <span>通过绝对定位分层</span></label></li> </ul> <button onclick="layer.create(1)">创建 1 个层</button> <button onclick="layer.create(10)">创建 10 个层</button> <button onclick="layer.create(20)">创建 20 个层</button> <button onclick="layer.create(50)">创建 50 个层</button> <button onclick="layer.create(100)">创建 100 个层</button> <button onclick="layer.create(200)">创建 200 个层</button> <button onclick="layer.create(500)">创建 500 个层</button> <button onclick="layer.create(1000)">创建 1000 个层</button> <button onclick="layer.create(2000)">创建 2000 个层</button> <button onclick="layer.create(5000)">创建 5000 个层</button> <button onclick="layer.create(10000)">创建 10000 个层</button>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    <style>.transform {
      transform: translateZ(0);
    }
    .animation {
      width:100px;
      height:100px;
      background:red;
      position:relative;
      animation:move 5s infinite;
    }
     
    @keyframes move {
      from {left:0px;}
      to {left:200px;}
    }
    </style>
    <script>
    var Layer = function() {
      function getType() {
        return document.querySelector('input:checked').value;
      };
      return {
        createOne: function(index) {
          var div = document.createElement('div');
          div.appendChild(document.createTextNode(index));
          switch(getType()) {
            case 'opacity':
              div.style.cssText = "opacity:" + (index / 1000);
              break;
            case  'transform':
              div.className = 'transform';
              break;
            case  'animation':
              div.className = 'animation';
              break;
            case  'zindex':
              div.style.cssText = "position:relative; z-index:" + index;
              break;
          }
          document.body.appendChild(div);
        },
        create: function(num) {
          [].slice.call(document.querySelectorAll('div')).forEach(function(item) {
            item.parentNode && item.parentNode.removeChild(item);
          });
          while(num--) {
            this.createOne(num);
          }
        }
      }
    };
    var layer = Layer();
    </script>
     
    <strong>层类型: </strong>
    <ul>
      <li><label><input type="radio" checked name="type" value="opacity"> <span>通过 opacity 创建层</span></label></li>
      <li><label><input type="radio" name="type" value="transform"> <span>通过 transforms 创建层</span></label></li>
      <li><label><input type="radio" name="type" value="animation"> <span>通过 animation 创建层</span></label></li>
      <li><label><input type="radio" name="type" value="zindex"> <span>通过绝对定位分层</span></label></li>
    </ul>
     
    <button onclick="layer.create(1)">创建 1 个层</button>
    <button onclick="layer.create(10)">创建 10 个层</button>
    <button onclick="layer.create(20)">创建 20 个层</button>
    <button onclick="layer.create(50)">创建 50 个层</button>
    <button onclick="layer.create(100)">创建 100 个层</button>
    <button onclick="layer.create(200)">创建 200 个层</button>
    <button onclick="layer.create(500)">创建 500 个层</button>
    <button onclick="layer.create(1000)">创建 1000 个层</button>
    <button onclick="layer.create(2000)">创建 2000 个层</button>
    <button onclick="layer.create(5000)">创建 5000 个层</button>
    <button onclick="layer.create(10000)">创建 10000 个层</button>
    • 实际上,创建多个层,也是对内存的巨大消耗,页面 Crash 可能还是因为内存消耗过大

    3. 并发过多问题

    • 测试方法:尝试并发发出多种不同的请求(Fetch请求、XHR 请求、Script/CSS 资源请求),观察页面 Crash 情况
    • 测试地址:

    XHTML

    <script> var Request = function() { function getType() { return document.querySelector('input:checked').value; }; function getResource() { var type = getType(); var resource = { fetch: '/', xhr: '/', script: '//g.alicdn.com/sd/data_sufei/1.5.1/aplus/index.js', css: '//g.alicdn.com/kg/global-util/1.0.3/index-min.css' }; return resource[type]; }; return { emitOne: function() { var url = getResource() + "?_t=" + (new Date * 1 + Math.random()); switch(getType()) { case 'fetch': return fetch('/'); case 'xhr': with(new XMLHttpRequest) { open('GET', url); send(); } return; case 'script': var s = document.createElement('script'); s.src = url; document.body.appendChild(s); return; case 'css': var s = document.createElement('link'); s.href = url; document.body.appendChild(s); } }, emit: function(num) { [].slice.call(document.querySelectorAll('script,link')).forEach(function(item) { item.parentNode && item.parentNode.removeChild(item); }); while(num--) { this.emitOne(); } } } }; var request = Request(); </script> <strong>请求类型: </strong> <ul> <li><label><input type="radio" checked name="type" value="fetch"> <span>使用 Fetch 发送请求</span></label></li> <li><label><input type="radio" name="type" value="xhr"> <span>使用 XHR 发送请求</span></label></li> <li><label><input type="radio" name="type" value="script"> <span>并发请求脚本资源</span></label></li> <li><label><input type="radio" name="type" value="css"> <span>并发请求样式资源</span></label></li> </ul> <button onclick="request.emit(1)">并发 1 个请求</button> <button onclick="request.emit(10)">并发 10 个请求</button> <button onclick="request.emit(20)">并发 20 个请求</button> <button onclick="request.emit(50)">并发 50 个请求</button> <button onclick="request.emit(100)">并发 100 个请求</button> <button onclick="request.emit(500)">并发 500 个请求</button> <button onclick="request.emit(1000)">并发 1000 个请求</button>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    <script>
    var Request = function() {
      function getType() {
        return document.querySelector('input:checked').value;
      };
      function getResource() {
        var type = getType();
        var resource = {
          fetch: '/',
          xhr: '/',
          script: '//g.alicdn.com/sd/data_sufei/1.5.1/aplus/index.js',
          css: '//g.alicdn.com/kg/global-util/1.0.3/index-min.css'
        };
        return resource[type];
      };
      return {
        emitOne: function() {
          var url = getResource() + "?_t=" + (new Date * 1 + Math.random());
          switch(getType()) {
            case 'fetch':
              return fetch('/');
            case 'xhr':
              with(new XMLHttpRequest) {
                open('GET', url);
                send();
              }
              return;
            case 'script':
              var s = document.createElement('script');
              s.src = url;
              document.body.appendChild(s);
              return;
            case 'css':
              var s = document.createElement('link');
              s.href = url;
              document.body.appendChild(s);
          }
        },
        emit: function(num) {
          [].slice.call(document.querySelectorAll('script,link')).forEach(function(item) {
            item.parentNode && item.parentNode.removeChild(item);
          });
          while(num--) {
            this.emitOne();
          }
        }
      }
    };
    var request = Request();
    </script>
     
    <strong>请求类型: </strong>
    <ul>
      <li><label><input type="radio" checked name="type" value="fetch"> <span>使用 Fetch 发送请求</span></label></li>
      <li><label><input type="radio" name="type" value="xhr"> <span>使用 XHR 发送请求</span></label></li>
      <li><label><input type="radio" name="type" value="script"> <span>并发请求脚本资源</span></label></li>
      <li><label><input type="radio" name="type" value="css"> <span>并发请求样式资源</span></label></li>
    </ul>
     
    <button onclick="request.emit(1)">并发 1 个请求</button>
    <button onclick="request.emit(10)">并发 10 个请求</button>
    <button onclick="request.emit(20)">并发 20 个请求</button>
    <button onclick="request.emit(50)">并发 50 个请求</button>
    <button onclick="request.emit(100)">并发 100 个请求</button>
    <button onclick="request.emit(500)">并发 500 个请求</button>
    <button onclick="request.emit(1000)">并发 1000 个请求</button>
    • 存在的干扰:设备的种类、设备的 CPU 使用情况和网络状况等。

    本文由奥门新浦京网址发布于Wed前段,转载请注明出处:到底是干什么的,创建对象的

    关键词: