• javascript的一些小知识点


    以下是我在学习过程中遇到的一些javascript的小知识点,保存下来以供参考,持续更新中。。

       1、eval函数的作用域

    eval 函数会在当前作用域中执行一段 JavaScript 代码字符串。但是 eval 只在被直接调用并且调用函数就是 eval 本身时,才在当前作用域中执行。如果执行了类似于 f = eval; f(); 这样的语句,将等价于在全局作用域中调用 eval,例如下面的这段代码:

    (原文来自《javascript秘密花园》:http://bonsaiden.github.com/JavaScript-Garden/zh/#core.eval

     1     var a = 0 ;
     2     var f1 = function() {
     3         var a = 1 ;
     4 
     5         eval("a = 2") ;     // 由于是直接调用eval函数,因此此时eval函数的作用域是当前作用域
     6         console.log(a) ;    // 2,在eval函数中修改了局部变量a
     7     };
     8     f1() ;
     9     console.log(a) ;        // 0,全局变量a没有被修改
    10 
    11     var b = 0 ;
    12     var f2 = function() {
    13         var b = 1 ;
    14         var f3 = eval ;
    15 
    16         f3("b = 2") ;       // 由于这里将eval函数的引用赋值给了变量f3,并通过f3调用了eval函数,因此此时该函数的作用域是全局作用域
    17         console.log(b) ;    // 1,局部变量a没有被修改
    18     }
    19     f2() ;
    20     console.log(b) ;        // 2,在eval函数中修改了全局变量a

       2、querySelector和getElementById的区别

    querySelector和getElementById的区别在于,querySelector的参数须是符合 css selector 的字符串,例如对于下面的这个div,用getElementById可以获取,但是querySelector就获取不到了:

    (参考出处:http://www.jb51.net/article/30132.htm

    1 <!DOCTYPE html>
    2 <html>
    3     <head>
    4         <meta charset="utf-8" />
    5     </head>
    6     <body>
    7         <div id="1"></div>
    8     </body>
    9 </html>

    输出结果如下:

    1 var div = document.getElementById("1");
    2 console.log(div);
    3 // =>  <div id="1"></div>
    4 
    5 var target = document.querySelector("#1");
    6 console.log(target);
    7 // => Uncaught Error: SYNTAX_ERR: DOM Exception 12

       3、querySelectorAll和getElementsByClassName的区别

    querySelectorAll和getElementsByClassName的区别在于querySelectorAll返回的是一个叫做StaticNodeList的新类型的实例。

    顾名思义,StaticNodeList有NodeList所有的属性和方法,但是它底层的实现是元素集合的一个快照,而非总是要重新的针对文档的动态查询。使用StaticNodeList消除了大部分使用NodeList对象带来的性能问题。

    只要调用querySelectorAll()都会返回一个StaticNodeList对象不管匹配的元素有几个;如果没有匹配,那么StaticNodeList为空。querySelectorAll()和querySelector()一样存在与Document和Element类型上。

    话不多说,上代码:(原文来自:http://www.poluoluo.com/jzxy/201204/163845.html

     1 <!DOCTYPE>
     2 <html>
     3     <head>
     4         <meta charset="utf-8" />
     5         <title>querySelectorAll和getElementsByClassName的区别</title>
     6     </head>
     7     <body>
     8         <div class="a"></div>
     9         <div class="a"></div>
    10         <div class="a"></div>
    11         <div class="a"></div>
    12         <div class="a"></div>
    13         <div class="a"></div>
    14     </body>
    15 </html>

    对于上面的7个div,分别通过querySelectorAll和getElementsByClassName获取它们,然后改变其中一个div的class值,观察两个集合的结果有没有发生变化:

     1 var div = document.getElementsByClassName("a");
     2 console.log(div);
     3 // => [<div>, <div>, <div>, <div>, <div>, <div>]
     4 
     5 var target = document.querySelectorAll(".a");
     6 console.log(target);
     7 // => [<div>, <div>, <div>, <div>, <div>, <div>]
     8 
     9 div[3].className = "b"; //改变第四个div的class值
    10 
    11 console.log(div);
    12 // => [<div>, <div>, <div>, <div>, <div>]
    13 // 动态NodeList显示出变更后的div集合
    14 
    15 console.log(target);
    16 // => [<div>, <div>, <div>, <div>, <div>, <div>]
    17 // StaticNodeList显示的还是变更前的div集合

       4、使用undefined不为人知的秘密

     在jQuery的源码中,其外层沙箱和命名空间大致是这样写的:

    (原文来自:http://blog.raphealguo.com/2013/01/17/jquery-src-util/

    1 (function(window, undefined) {
    2     ...
    3 
    4     window.jQuery = window.$ = jQuery;
    5 
    6 }(window, undefined));

    这里最外层的匿名函数使用undefined作为第二个参数的原因,是因为在jQuery中有一个针对压缩的小小策略,先看以下代码:

    1 (function( window, undefined ) {
    2   var a = undefined;
    3   if (a == undefined){blabla...}
    4  
    5   ....
    6   if (c == undefined) return;
    7 })( window );

    经过压缩后,可以变成:

    1 (function(w, u) {
    2   var a = u;
    3   if (a == u){blabla...}
    4  
    5   ....
    6   if (c == u) return;
    7 })(w);

    因为这个外层函数只传了一个参数,因此沙箱执行时,u自然会undefined,把9个字母缩成1个字母,可以看出压缩后的代码减少一些字节数。

     这样做还有另外一个原因:由于在ECMAScript5之前undefined并不是ECMAScript中的关键字,即undefined是可以用作变量名的,也就是undefined是可以赋值的。例如下面所示的这段代码:

    1 var undefined = "zhaojian";
    2 
    3 (function() {
    4     console.log(undefined);   
    5 }());

    这段代码在ES5之前是合法的,控制台输出的结果可能会是zhaojian而非undefined。因此将undefined作为参数传入的用处就是防止某些2B程序员对undefined进行赋值,并且即使某个2B程序员真的这么做了,那么这样做的影响也只局限于这一块代码的范围,不会影响到全局范围内其他人的代码。

     

       5、深入理解形参、实参与arguments

    arguments对象的值只与实参有关,而与实参无关,arguments与形参的关系是通过实参联系起来的。

    先来看看下面的几道面试题:(原文出自:http://hi.baidu.com/flondon/item/544b53b5d4872870254b0999

     1 function tmp(x) {
     2     x = 10;
     3     console.log(arguments[0]);
     4 }
     5 tmp(1);
     6 
     7 function tmp(x) {
     8     arguments[0] = 10;
     9     console.log(arguments[0]);
    10 }
    11 tmp(1)
    12 
    13 function tmp(x) {
    14     arguments[0] = 10;
    15     console.log(arguments[0]);
    16 }
    17 tmp();
    18 
    19 function tmp(x) {
    20     x = 10;
    21     console.log(arguments[0]);
    22 }
    23 tmp();
    24 
    25 function tmp(x, y) {
    26     y = 10;
    27     console.log(arguments[1]);
    28 }
    29 tmp(1);

     在上面的五道题中,前两道的答案都为10,后三道的答案都为undefined。关于该答案的要点分析如下:

    1、如果函数调用时没有参数传入,那么arguments对象为空(已经声明,但没有元素,并且不指向任何内存单元)。

    2、如果函数调用时有参数传入,那么arguments对象和相应的形参同时指向这些传入值的内存单元,此时,对arguments对象中的元素或者函数形参的任何赋值都会直接体现到彼此(因为它们的值存储于同一块内存)。

    3、当输入的参数少于形参数目时,其他形参(未传入实参)值的改变不影响arguments的值(如代码段5)。

       6、for in 遍历稀疏数组的问题

    在使用for in方式遍历数组的时候,它会在遍历过程中跳过没有定义的数组位置。例如下面的代码:

    1 var arr = [];
    2 arr[1] = 1;                          // arr = [undefined, 1]
    3 console.log(0 in arr);                // false
    4 console.log(arr.indexOf(undefined));  // -1
    5 console.log(arr[0] === undefined);    // true

    对于上面的数组,js认为它的第一项是不存在的,虽然它有一个undefined的默认值,但是如果用indexOf去寻找值为undefined的数组元素,返回的结果是找不到(-1)。

    上面的是正常的情况,但是有正常就有不正常,例如下面的代码:

    1 var arr = [undefined, 1];              // arr = [undefined, 1]
    2 console.log(0 in arr);                  // true
    3 console.log(arr.indexOf(undefined));    // 0
    4 console.log(arr[0] === undefined);      // true            

    对于这里的数组,js认为它的第一项是存在的,虽然它的值也为undefined,而且如果用indexOf去寻找值为undefined的数组元素是能找到的(返回结果为0)。

    因此可以得出结论,虽然上面的两个数组从外表上看起来一模一样,但是第二个数组中的undefined值是显式声明的,而第一个数组中的undefined值是隐式声明的,所以for in会忽略隐式声明的undefined数组元素,而把显示声明的数组元素作为正常的数组元素来看待

     

  • 相关阅读:
    350 Intersection of Two Arrays II 两个数组的交集 II
    349 Intersection of Two Arrays 两个数组的交集
    347 Top K Frequent Elements 前K个高频元素
    345 Reverse Vowels of a String 反转字符串中的元音字母
    344 Reverse String 反转字符串
    343 Integer Break 整数拆分
    342 Power of Four 4的幂
    338 Counting Bits Bit位计数
    Java常见面试题之Forward和Redirect的区别
    字节、字、bit、byte的关系
  • 原文地址:https://www.cnblogs.com/ZJAJS/p/2737988.html
Copyright © 2020-2023  润新知