JS趣味见闻2

日期:2015-12-29 22:44 | 标签: | 阅读:492

这里记录我平常使用JS时遇到的好玩的东东,当然,如果您见得多了话,也就见怪不怪了.

JS 是值传递而非引用传递

证明可以参考以下代码

function setName(obj){
    obj.name = "test";
    obj = new Object();
    obj.name = "py";
}
var person = new Object();
setName(person);
alert(person.name); // 结果依旧是 test

input text 光标玩定位

(0, foo.bar)()

(0, foo.bar)(),这个逗号表达式等价于执行 foo.bar(),但是执行时的上下文环境会被绑定到全局对象身上,所以实际上真正等价于执行 foo.bar.call(GLOBAL_OBJECT)

JS内存访问结构

按位取反!~

~表示按位取反,(负数的反码为符号位取反,数值位-1?)

57的二进制表示为(1个字节):00111001 按位取反后(~57)的二进制: 11000110 此表示为十进制:-70 这是一个负数,是有符号的数,负数在计算机里要用其补码来表示:补码=符号位以后按位取反再加1. 所以-70(11000110)符号位以后按位取反后为(10111001) 再加1 则为(10111010) 换成十进制为:-58 因此~57=-58

change事件与click事件冲突

需求是需要先执行click事件,但是change事件先执行了,而且阻止了click事件的执行,需要调整下执行顺序,方法有2:

  1. 在change事件中使用setTimeout
  2. 把click事件改为 mousedown

'' instanceof String

答案是false,其实翻译而来该是对象 instanceof 构造函数,不过由此引出了对instanceof 用法的讨论,不妨看看如何用js模拟instanceof

function _instanceof(A, B) {
    var O = B.prototype;// 取B的显示原型
    A = A.__proto__;// 取A的隐式原型
    while (true) {
        //Object.prototype.__proto__ === null
        if (A === null)
            return false;
        if (O === A)// 这里重点:当 O 严格等于 A 时,返回 true
            return true;
        A = A.__proto__;
    }
}

再举两个特殊的用法,整懂了话,对理解instanceof该没问题了:

Function instanceof Function  
Object instanceof Object

$.isPlainObject

jquery对plainobject的判断源码如下,此方法一般用在深拷贝中

function isPlainObject(obj) {
    var key;
    if (!obj || type(obj) !== 'object' ||
        obj.nodeType || 'setInterval' in obj) {
        return false;
    }

    if (obj.constructor &&
        !hasOwn.call(obj, 'constructor') &&
        !hasOwn.call(obj.constructor.prototype, 'isPrototypeOf')) {
        return false;
    }

    for (key in obj) {}
    return key === undefined || hasOwn.call(obj, key);
}

with

with在JavaScript语言精髓中被称作毒瘤,其性能问题也很堪忧,但是偶尔能够像这样子写写也是很不错的。

with(obj.style){
            left = 10;
            top = 20;
}

Function

  1. 函数名实际上是一个指向函数对象的指针,不会与某个函数绑定
    var f1=function(){console.log('i am a function.');};
    var f2 = f1;
    f1 =null;
    f2();
    
    这个其实无须惊奇,JS对var的处理都是一样的
    var f1={a:1};
    var f2 = f1;
    f1 =null;
    console.log(f2);
    
  2. 请说明为什么在fun内访问不到_f和_ff(函数表达式不会影响到执行上下文)
    function fun() {
     var f = function _f() {};
        (function _ff() {})
    }
    
  3. 变量声明遇到命名冲突会选择忽略,而函数会选择覆盖
  4. Function的bind怎么实现?(柯里化)
    if (!function() {}.bind) {
    Function.prototype.bind = function(context) {
        var self = this
            , args = Array.prototype.slice.call(arguments);
        return function() {
            return self.apply(context, args.slice(1));    
        }
    };
    }
    

prototype&__proto__

prototype是函数的内置属性,''proto''是对象的内置属性(ie不能用)。

(对象.__proto__ === 函数.prototype)

上述表达式返回true。

通过坐标获取元素

获取touch时经过的元素时有用。

$('#element').on("touchmove",function(event){
    var endTarget = document.elementFromPoint(
        event.originalEvent.touches[0].pageX,
        event.originalEvent.touches[0].pageY
    );
});

参考:http://www.zehnet.de/2010/11/19/document-elementfrompoint-a-jquery-solution/

touch事件

让人印象最深的是touch事件的各个属性了,顿时傻傻分不清楚:

  1. touches: 当前屏幕上所有触摸点的集合列表
  2. targetTouches: 绑定事件的那个结点上的触摸点的集合列表
  3. changedTouches: 触发事件时改变的触摸点的集合

三目运算符

考考运算符优先级啦

'ds' + (1==1? 1:3)
'ds' + 1==1? 1:3
'ds'+ 'ds' + 1==1? 1:3
'ds' + 1==1? 1:3 +'aa'

Object.assign

Object.assign对应的Polyfill如下

if (!Object.assign) {
  Object.defineProperty(Object, "assign", {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(target, firstSource) {
      "use strict";
      if (target === undefined || target === null){
          throw new TypeError("Cannot convert first argument to object");
      }
      var to = Object(target);
      for (var i = 1; i < arguments.length; i++) {
        var nextSource = arguments[i];
        if (nextSource === undefined || nextSource === null) {
            continue;
        }
        var keysArray = Object.keys(Object(nextSource));
        for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
            var nextKey = keysArray[nextIndex];
            var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
            if (desc !== undefined && desc.enumerable) {
                to[nextKey] = nextSource[nextKey];
            }
        }
      }
      return to;
    }
  });
}

时间(Date)

requestIdleCallback

在浏览器空闲时执行代码。
参考: http://www.cnblogs.com/galenyip/p/4856996.html

/*
 * @see https://developers.google.com/web/updates/2015/08/using-requestidlecallback
 */
window.requestIdleCallback = window.requestIdleCallback ||
  function (cb) {
    var start = Date.now();
    return setTimeout(function () {
      cb({ 
        didTimeout: false,
        timeRemaining: function () {
          return Math.max(0, 50 - (Date.now() - start));
        }
      });
    }, 1);
  }

window.cancelIdleCallback = window.cancelIdleCallback ||
  function (id) {
    clearTimeout(id);
  }

异常监控

发现一段有意思的代码,这里做点小小的记录,至少不要对每个方法都去写 trycatch 了,具体参见:原文地址

var a = {
  b: function() {
    throw new Error("a -> b is not comfortable");
  }
};

for (var prop in a) {
  var mthod = a[prop];
  if (typeof mthod == "function") {
    a[prop] = function(prop, mthod) {
      return (function() {
        try {
          return mthod.apply(this, arguments);
        } catch (error) {
          console.error(error);
        }
      });
    }(prop, mthod);
  }
}

a.b();

版权声明: 署名-非商业性使用-禁止演绎 4.0 国际(CC BY-NC-ND 4.0
Copyright ©2013-2017 | 粤ICP备14081691号 | yipeng手工打造 | 联系方式