zoukankan      html  css  js  c++  java
  • js几个经典的题目详解

    直接看题目,先不要急着看答案 先自己思考,收获更多

    var out = 25,
       inner = {
            out: 20,
            func: function () {
                var out = 30;
                return this.out;
            }
        };
    console.log((inner.func, inner.func)());
    console.log(inner.func());
    console.log((inner.func)());
    console.log((inner.func = inner.func)());
    

    25,20,20,25
    
    代码解析:这道题的考点分两个 
    1.作用域
    2.运算符(赋值预算,逗号运算)
    
    先看第一个输出:25,因为(inner.func, inner.func)是进行逗号运算符,逗号运算符就是 运算前面的,
    返回最后一个,举个栗子
    
    var i=0,j=1,k=2;
    console.log((i++,j++,k))//返回的是k的值 2 ,如果写成k++的话  这里返回的就是 3
    console.log(i);//1
    console.log(j);//2
    console.log(k);//2   
    
    回到原题(inner.func, inner.func)就是返回inner.func而inner.func只是一个匿名函数 
    function () {
        var out = 30;
        return this.out;
    }
    而且这个匿名函数是属于window的
    则变成了
    (function () {
        var out = 30;
        return this.out;
    })()
    此刻的this--》window
    
    所以out 是25
    
    第二和第三个console.log的作用域都是 foo,也就是他们执行的其实是
    foo.func();
    foo作用域中是有out变量的,所以结果是20
    
    第四个console.log
    考查的是一个等号运算inner.func = inner.func 其实返回的是运算的结果,
    举个栗子
    var a=2,b=3;
    console.log(a=b)//输出的是3
    所以inner.func = inner.func 返回的也是一个匿名函数
    function () {
        var out = 30;
        return this.out;
    }
    
    此刻 道理就和第一个console.log一样了 输出的结果是 25
    

    if (!("a" in window)) {
        var a = 1;
    }
    alert(a);
    
    

    
    
    
    
    
    代码解析:如果window不包含属性a,就声明一个变量a,然后赋值为1。
    
    你可能认为alert出来的结果是1,然后实际结果是“undefined”。要了解为什么,
    需要知道JavaScript里的3个概念。
    
    首先,所有的全局变量都是window的属性,语句 var a = 1;等价于window.a = 1;
    
    你可以用如下方式来检测全局变量是否声明:"变量名称" in window
    第二,所有的变量声明都在范围作用域的顶部,看一下相似的例子:   
    
    alert("b" in window);
    var b;
    
    此时,尽管声明是在alert之后,alert弹出的依然是true,这是因为JavaScript引擎
    首先会扫墓所有的变量声明,然后将这些变量声明移动到顶部,最终的代码效果是这样的:
    
    var a;
    alert("a" in window);
    这样看起来就很容易解释为什么alert结果是true了。
    
    第三,你需要理解该题目的意思是,变量声明被提前了,
    但变量赋值没有,因为这行代码包括了变量声明和变量赋值。
    
    你可以将语句拆分为如下代码:
    
    var a;    //声明
    a = 1;    //初始化赋值
    当变量声明和赋值在一起用的时候,JavaScript引擎会自动将它分为两部以便将变量声明提前,
    不将赋值的步骤提前是因为他有可能影响    代码执行出不可预期的结果。
    
    所以,知道了这些概念以后,重新回头看一下题目的代码,其实就等价于:
    
    var a;
    if (!("a" in window)) {
        a = 1;
    }
    alert(a);
    这样,题目的意思就非常清楚了:首先声明a,然后判断a是否在存在,如果不存在就赋值为1,
    很明显a永远在window里存在,这个赋值语    句永远不会执行,所以结果是undefined。
    
    提前这个词语显得有点迷惑了,你可以理解为:预编译。
    

       var a = 1;
    
       var b = function a(x) {
                x && a(--x);
            };
     
       alert(a);
    
    

    这个题目看起来比实际复杂,alert的结果是1;这里依然有3个重要的概念需要我们知道。
    
    首先,在题目1里我们知道了变量声明在进入执行上下文就完成了;第二个概念就是函数声明也是提前的,
    所有的函数声明都在执行代码之前都已经完成了声明,和变
    
    量声明一样。澄清一下,函数声明是如下这样的代码:
    
    function functionName(arg1, arg2){
        //函数体
    }
    如下不是函数,而是函数表达式,相当于变量赋值:
    
    var functionName = function(arg1, arg2){
           //函数体
       };
    澄清一下,函数表达式没有提前,就相当于平时的变量赋值。
    
    第三需要知道的是,函数声明会覆盖变量声明,但不会覆盖变量赋值,为了解释这个,我们来看一个例子:
    
    function value(){
        return 1;
    }
    var value;
    alert(typeof value);    //"function"
    尽快变量声明在下面定义,但是变量value依然是function,也就是说这种情况下,
    函数声明的优先级高于变量声明的优先级,但如果该    变量value赋值了,那结果就完全不一样了:
    
    function value(){
        return 1;
    }
    var value = 1;
    alert(typeof value);    //"number"
    该value赋值以后,变量赋值初始化就覆盖了函数声明。
    
    重新回到题目,这个函数其实是一个有名函数表达式,函数表达式不像函数声明一样可以覆盖变量声明,
    但你可以注意到,变量b是包含了该函数表达式,而该函数表达式的名字是a;不同的浏览器对a这个名
    词处理有点不一样,在IE里,会将a认为函数声明,所以它被变量初始    化覆盖了,就是说如果调用a(–x)的
    话就会出错,而其它浏览器在允许在函数内部调用a(–x),因为这时候a在函数外面依然是数字。
    基本上,IE里调用b(2)的时候会出错,但其它浏览器则返回undefined。
    
    理解上述内容之后,该题目换成一个更准确和更容易理解的代码应该像这样:
    
    var a = 1,
        b = function(x) {
        x && b(--x);
        };
    alert(a);
    这样的话,就很清晰地知道为什么alert的总是1了。
    

    function a(x) {
        return x * 2;
    }
    var a;
    alert(a);
    

    这个题目比较简单:即函数声明和变量声明的关系和影响,遇到同名的函数声明,不会重新定义
    
    

    4、function b(x, y, a) {
            arguments[2] = 10;
            alert(a);
        }
        b(1, 2, 3);
    

    关于这个题目,ECMAsCRIPT 262-3的规范有解释的。
    
    活动对象是在进入函数上下文时刻被创建的,它通过函数的arguments属性初始化。
    arguments属性的值是Arguments对象.
    关于 Arguments对象的具体定义,看这里:ECMAScript arguments 对象
    

        function a() {
            alert(this);
        }
        a.call(null);
    

     
    这个题目可以说是最简单的,也是最诡异的!关于这个题目,我们先来了解2个概念。
    
    这个问题主要考察 Javascript 的 this 关键字,具体看这里:
    
    关于Javascript语言中this关键字的用法
    
    关于 a.call(null);  根据ECMAScript262规范规定:如果第一个参数传入的对象调用者是null
    或者undefined的话,call方法将把全局对象(也就是window)作为this的值。所以,
    不管你什么时候传入null,其this都是全局对象window,所以该题目可以理解成如下代码:
    function a() {
        alert(this);
    }
    a.call(window);
    所以弹出的结果是[object Window]就很容易理解了。

    var a={}, b={key:'b'}, c={key:'c'}; 

    a[b]=123; a[c]=456;

     console.log(a[b]);//456

    原因:当使用一个引用类型·当做某个对象的属性来赋值,都会隐式的调用toString()方法

    在执行a[b] = 123的时候,会用b作key,而b是个对象,实际执行的是a[b.toString()] = 123,即a['[object Object]'] = 123,

    同理执行a[b] = 456时,实际执行的是a[c.toString()] = 456,即a['[object Object]'] = 456

    由于b.toString()和c.toString()都等于'[object Object]',等于在同一个key上赋值了,后者覆盖了前者,所以为456.

     
  • 相关阅读:
    【第40套模拟题】【noip2011_mayan】解题报告【map】【数论】【dfs】
    【模拟题(63550802...)】解题报告【贪心】【拓扑排序】【找规律】【树相关】
    【模拟题(电子科大MaxKU)】解题报告【树形问题】【矩阵乘法】【快速幂】【数论】
    IMemoryBufferReference and IMemoryBufferByteAccess
    SoftwareBitmap and BitmapEncoder in Windows.Graphics.Imaging Namespace
    Windows UPnP APIs
    编译Android技术总结
    Windows函数转发器
    Two Ways in Delphi to Get IP Address on Android
    Delphi Call getifaddrs and freeifaddrs on Android
  • 原文地址:https://www.cnblogs.com/yzhihao/p/6528943.html
Copyright © 2011-2022 走看看