Skip to content
LYF edited this page Jun 12, 2018 · 40 revisions

一、闭包闭住公共变量

var ZingTouch = {
    _region:[], // 公共变量
    Region: function(){
        var id = ZingTouch._region.length;
        console.log(id);
        ZingTouch._region.push(obj);
    }
}

var region = new ZingTouch.Region(); // 0
var region2 = new ZingTouch.Region();// 1
var region3 = new ZingTouch.Region();// 2

https://github.com/zingchart/zingtouch/blob/master/src/ZingTouch.js

二、不知道作用

var Trigger = function(_element) {
  this.element = _element;
  this.left = function(_this){
     return function(){
       return _this.element.left
     }  
  }(this)
}

https://github.com/terwanerik/ScrollTrigger/blob/master/ScrollTrigger.js

三、定义私有变量

var Trigger = function(_element){
   this.element = _element;
   var xoffset = 0; // 私有变量
   var yoffset = 0; // 私有变量
}

https://github.com/terwanerik/ScrollTrigger/blob/master/ScrollTrigger.js

四、看avalon源码,很屌的写法

// 惰性函数
function CSPHack(array){
     var a = array.reverse().join("")
     return function(v){
         return window[a].apply(0, v)
     }
     return window
 }
 var CSPcompile = CSPHack(["n","o","i","t","c","n","u", "F"])

 // 类似于
 // var f = Function.apply(0,['a','b','return a + b'])
 // f(2, 3); // 5
 function CSPcompile(array){
     return Object.constructor.apply(0,array)
}

// 一个小技巧。由于与this相关,js引擎总能保证this是一个引用值,所以用call/apply方法时,context随便,第一个参数可写成0,比写成null要好

五、jquery free写法

var $ = document.querySelectAll.bind(document);

六、取整的另一种方法

var a = 12.3;
a |= 0;
console.log(a); // 12

a = -9.512;
a |= 0;
console.log(a); // -9

七、稀疏数组处理

var arr = Array(10); // [undefined × 10]
 
arr[3] = 999;

arr[8] = void 0;

for(var i = 0, n = arr.length; i < n; i++){

   if( i in arr ){
 
      console.log(arr[i]); // 999, undefined

   }  

}

八、判断环境是否是ES5+

var isES5 = (function(){
    "use strict";
    return this === undefined;
})();

bluebird中看到这种写法

九、bluebird

var isES5 = (function(){
    "use strict";
    return this === undefined;
})();

if (isES5) {
    module.exports = {
        freeze: Object.freeze,
        defineProperty: Object.defineProperty,
        getDescriptor: Object.getOwnPropertyDescriptor,
        keys: Object.keys,
        names: Object.getOwnPropertyNames,
        getPrototypeOf: Object.getPrototypeOf,
        isArray: Array.isArray,
        isES5: isES5,
        propertyIsWritable: function(obj, prop) {
            var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
            return !!(!descriptor || descriptor.writable || descriptor.set);
        }
    };
} else {
    var has = {}.hasOwnProperty;
    var str = {}.toString;
    var proto = {}.constructor.prototype;

    var ObjectKeys = function (o) {
        var ret = [];
        for (var key in o) {
            if (has.call(o, key)) {
                ret.push(key);
            }
        }
        return ret;
    };

    var ObjectGetDescriptor = function(o, key) {
        return {value: o[key]};
    };

    var ObjectDefineProperty = function (o, key, desc) {
        o[key] = desc.value;
        return o;
    };

    var ObjectFreeze = function (obj) {
        return obj;
    };

    // 记住这个技巧:在try中进行运算,若发生了异常,在catch中返回
    // 这样就在不支持或有问题的环境中,也能返回想要的结果
    var ObjectGetPrototypeOf = function (obj) {
        try {
            return Object(obj).constructor.prototype;
        }
        catch (e) {
            return proto;
        }
    };
    
    // 记住这个技巧。catch中return
    var ArrayIsArray = function (obj) {
        try {
            return str.call(obj) === "[object Array]";
        }
        catch(e) {
            return false;
        }
    };

    module.exports = {
        isArray: ArrayIsArray,
        keys: ObjectKeys,
        names: ObjectKeys,
        defineProperty: ObjectDefineProperty,
        getDescriptor: ObjectGetDescriptor,
        freeze: ObjectFreeze,
        getPrototypeOf: ObjectGetPrototypeOf,
        isES5: isES5,
        propertyIsWritable: function() {
            return true;
        }
    };
}

十、全局变量获取

顺序是:self -> window -> global -> this -> null

var globalObject = typeof self !== "undefined" ? self :
    typeof window !== "undefined" ? window :
    typeof global !== "undefined" ? global :
    this !== undefined ? this : null;

十一、defineProperty

var obj = {b: 2};

Object.defineProperty(obj, 'a', {
  enumerable: true,
  configurable: true,
  get: function(){
    console.log(this); // {b: 2}
    return 999;
  },
  set: function(v){
    console.log(this); //{b: 2}
    this.a = v; // 不能这样干,会栈溢出的
  }
})

十二、删除任意子节点

/*
将一个节点appendChild
它必须从原来的父节拔出
总是放在那个文档碎片中,会内存释放不了
这是不确定它有没有父节点,不知道父节点时的移除节点的方式

如果不知道这个节点的父节点,删除这个节点将会报错:
 Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
*/

function removeNode(node){
  var f = document.createDocumentFragment();
  f.appendChild(node);
  f.removeChild(node);
  return node;
}

/**
    * 一个节点如果放到文档碎片中,那么就会从页面删除
    */
    function node2Fragment(node, vm) {
      //这里是dom劫持,vue会新建一个文档片段来替换dom中本来的结点
      var flag = document.createDocumentFragment();
      //子节点
      var child;
      while (child = node.firstChild) {
        console.log('child:', child)
        //开始编译每个结点
        // compile(child,vm);
        //appendchild方法会自动删除node对象的child结点
        flag.appendChild(child)
      }
      return flag;
    }

十三、JSON.parse(JSON.stringify(obj))

作用:

1、深拷贝一个对象

2、干掉obj中的所有function

如果深拷贝时,需要带上所有function属性,那么就不能使用这种方式了。

十四、String数组元素Number化

这个技巧很好用。是在vue中看到的。也可以举一反三,进行任意转化。

var strArr = ['1','2','3'];

var numArr = strArr.map(Number);

十五、做好模块化与方法封装

在开发全屏查看组件时的心得,全屏查看组件目前有2个功能:

  1. 全屏查看
  2. 图片懒加载

这2个功能点要做好区分,不要耦合,这样再改全屏查看的功能时,不会影响图片懒加载的功能

若耦合在一起的话,修改全屏查看,极大可能会导致图片懒加载功能出错,需要重新测试图片懒加载功能。

要在方法层面遵循单一职责原则,这样在改代码时,改一个单一职责的方法比改大杂烩方法方便容易的多了,也不容易出错!!

十六、一段可以研究一下的代码

var oEvent = {};  
(function(){   
    var addEvent = function(){ /*代码的实现省略了*/ };  
    function removeEvent(){}  
     
    oEvent.addEvent = addEvent;  
    oEvent.removeEvent = removeEvent;  
})();

Javascript的匿名函数与自执行

十七、一段难懂的代码

// 实现连乘
function count(x){

 var fn = function(y){
      return count(x*y);
 }
 fn.toString = function(){ // 前面的还好理解,关键是这句话。
      return x;
 };
 return fn;
}
alert(count(1)(3)(5)); // 15

十八、听说是react处理children的算法

注意一个小技巧,如果判断一个类型为一组类型中的某个,则可以用/null|object|boolean/.test(type)

function flatChildren(array, ret) {
      ret = ret || []
      for (var i = 0, n = array.length; i < n; i++) {
        var el = array[i]
        var type = typeof el
        if (!el && /null|object|boolean/.test(type)) {
          continue
        }
        if (/number|string/.test(type)) {
          if (el === '') {
            continue
          }
          if (ret.merge) {
            ret[ret.length - 1] += el
          } else {
            el = String(el)
            ret.push(el)
            ret.merge = true
          }
        } else if (Array.isArray(el)) {
          flatChildren(el, ret)
        } else {
          ret.push(el)
          ret.merge = false
        }

      }
      return ret
    }

十九、异步的写法

var promises = [], ar, br
  function getNextEvent(){
    return  promises.shift()
  }
    promises.push(new Promise(function(r){
     ar = r
  }), new Promise(function(r){
      br = r
  }))
 
   document.addEventListener("touchstart", function(e){
 	 ar(e)
    promises.push(new Promise(function(r){
       ar = r
      }))
  })
  document.addEventListener("mousedown", function(e){
    br(e)
    promises.push(new Promise(function(r){
       br = r
      }))
  })


const readFileAsync = async function () {
  while(promises.length){
   let e = await getNextEvent()
   console.log(e.type)
  }
}
Clone this wiki locally