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]就很轻易明白了。
    原文作者:spademan
    原文地址: https://segmentfault.com/a/1190000003860689
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞