zoukankan      html  css  js  c++  java
  • js便签笔记(9)——解读jquery源码时记录的一些知识点

    近来一直利用业余时间在看jquery2.1.1源码,大约看了两千行了。平时看的时候,做了一些笔记,贴出来分享。

    1. Array.prototype.slice.call 可以将伪数组转化为真正的数组

    其实,这里所谓的“伪数组”就是有length属性,并且有“0”、“1”、“2”等这些属性的对象,如下代码:

    var obj = {
                0: "A",
                1: "B",
                2: "C",
                length: 3
            };
            var slice = [].slice;
            console.log(slice.call(obj));

    这里打印的结果就是一个真正的数组:

    另外,我们平时所写的 $('div') ,其实也是这种伪数组,可以看一下:

    jquery源码中有一个方法是用来判断是否是伪数组的,其中就是根据对象是否有length属性,并且对象的[length - 1]属性有没有值,来判断的。这样判断会排除掉一个特殊的类型——String,string有length属性,但是它的确不是伪数组。

    上面代码中,slice.call不仅能将伪数组转化成真正的数组,还能想数组的slice一样,截取元素。如下:

    打印的结果可想而知:

    2. window对象还有一个“window”属性

     jquery源码中,判断一个对象是否是window的时候,用以下方法来判断:

     return obj.window === window;

    用浏览器监测以下window对象的细节,会发现,window对象下确实还有一个window对象,而且是一个无限循环的结构。

    3.  快捷方法

    第一:

    第二:

    将一个对象强制转换为与之对应的bool类型,可用: !!obj

    相反,如果转换成一直相反的bool类型,可用: !obj

    4. === 与 ==

    === 是严格相等,不会进行类型转换,而 == 是不严格相等,会进行类型转换。有些js的书中,建议开发人员永远不要用 == 或者 != 。

    但是jquery源码中,有用到“==”或者“!=”的情况 —— 判断 undefined 和 null 的时候。

    5. 重写了 toString()

    有些对象类型重写了 toString 方法,因此要获取这个对象的名称,就不能简单的用 .toString() ,而是用 Object.prototype.toString.call

    var a = [1, 2];
    console.log(a.toString());   // 1,2
    console.log(Object.prototype.toString.call(a));   // [Object Array]

    6. Object( 'str' ) —— String强制类型转换为Object

     将一个字符串强制类型转换成object之后,将会返回一个标准的伪数组对象。

    Object( 'abc' )  -->  String {0: "a", 1: "b", 2: "c", length: 3}

    7. jQuery的each函数,最大的优点

    each函数相比于for循环,最大的改进在于封闭了独立的函数作用域。

    先看一段for循环的代码:

                console.log("current this", this);
    
                var $divs = $("div"),
                    index = 0,
                    length = $divs.length;
    
                for (; index < length; index++) {
                    console.log(index, this);
                    var j = 200;
                }
    
                console.log(j);

    打印的结果如下:

    打印结果可以看出:for循环里面的语句块,和外面的作用域相同;最可怕的是 for 循环里面定义的变量,在外面可以识别。 别伤心,这就是js的一个“特点”。

    为了解决这个问题,我们再看看each函数的代码:

                console.log("current this", this);
    
                var $divs = $("div");
    
                $divs.each(function (index, elem) {
                    console.log(index, this);
                    var x = 100;
                });
                console.log(x);

    打印结果如下:

    很容易看出,each函数中的作用域,和外部作用域不同,而且each函数中定义的变量完全是局部变量,外面不可获取。这正式我们想要的!

    另外,大家还肯能会发现,each比较类似与 for ... in 。 for...in 是迭代器模式,比 for(i=0;i<length;i++)要方便很多。但是除了上面提到了作用域之外,each和for...in就完全一样了吗? 当然不是!

    以上两段代码,结果却大相径庭。为何? 因为 for...in 会遍历一个对象的隐式原型元素,而 each 则像for(i=0;i<length;i++)一样中规中矩。

    8. call和apply的参数传递不同

    他俩的传参方式不同可能大家都知道,说一个具体的例子吧,jquery中用到的。

    var arr = [5, 6, [1, 2], [3, 4]];
    console.log(Array.prototype.concat.call([], arr));     // [5, 6, [1, 2], [3, 4]]
    console.log(Array.prototype.concat.apply([], arr));    // [5, 6, 1, 2, 3, 4]

    以上代码,输出的结果完全不一样。看明白这一点,才能说明你真正理解了两者传参的不同。

    ---------------------------------------------------------------

    以上是本次全部内容。jquery还会继续往下看,笔记也会继续整理。再有新内容,再分享。

  • 相关阅读:
    数据恢复
    InnoDB LRU优化
    STM32 M0之SPI
    C# 添加日志文件
    VCI_CAN二次开发摘机
    [一点感触]ADF4350 ADF4111混频记
    Linux札记
    C# String与Byte数组的转换
    STM32 CAN
    stm32 F40x CCM数据区的使用
  • 原文地址:https://www.cnblogs.com/wangfupeng1988/p/3773267.html
Copyright © 2011-2022 走看看