测试一

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

测试二

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

测试三

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

测试四

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

测试五

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

----------------------------------------------------------------- 答案分水岭 ------------------------------------------------------------------

答案:

1. undefined
2. 1
3. function a(x) { return x * 2; }
4. 10
5. window

讲解:

第一题

if (!("a" in window)) {
    var a = 1;
}
alert(a);
这段代码用语言描述就是"如果window没有属性a,那么定义a等于1". 也许有人就会认为结果是1了.但测试
才会发现弹出的是undefined.这是问什么呢?
这个问题考察以下两点:
1) 所有的全局变量都是window的属性. var a = 1实际上相当于window.a = 1. 所以你可以使用
"variable-name" in window来检测一个全局变量是否被定义.

2) 所有被var的变量声明 都要被提到作用域的顶部.考虑一个简单的例子:
alert("a" in window);
var a;
这个结果会弹出true;尽管变量定义在后面. 这是因为javascript引擎首先扫描定义的变量并把他的作用域提到顶部. 所以上面的代码近似于这样:
var a;
alert("a" in window);
读这段代码,你就会更清楚为什么弹出的是true.

3) 你需要知道咱们测试例子 当变量作用域定义并提前了.但却并没有初始化.下面这句是定义变量并初始化
var a = 1;
你可以分开看定义变量和初始化:
var a; //定义
a = 1; 初始化
但JS引擎解析一个合并的var a = 1;是自动将其分离的.所以可以将定义被提前.但为什么值不提前呢? 因为值会影响到后面的值而导致不可预知的结果出现.

所以.知道了上面这三点.重新思考下刚才的例子.其实就可以分解为
var a;
if (!("a" in window)) {
    a = 1;
}
alert(a);
这样就可以看出if检测的时候a已经被定义了 默认为undefined所以分支不会走 最后弹出了'undefined'

第二题

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

这个例子看上去要比实际复杂.这个结果显示1. 主要是看哪个a最后被实例化了.这个问题也需要搞清3个知识点.

1) 就是定义的变量作用域被提前.这个在实例1已经讲解了.

2) 就是所有的function定义的作用域也随着var变量定义一起提前.但必须搞清楚的是.一个函数定义是这样子的:
function functionName(arg1, arg2){
    //function body
}
这个要区别于函数表达式.函数表达式是赋予一个变量,是这样的:
var functionName = function(arg1, arg2){
    //function body
};
要搞清楚的是.函数表达式不会作用域提前.这样应该意识到.如果将value初始化值,从代码的一段移到另一段会产生影响.

3) 就是要必须理解记住函数声明重写的是变量声明.但不是变量初始化.理解这句话考虑下面的例子
function value(){
    return 1;
}
var value;
alert(typeof value);    //"function"
尽快变量声明在函数声明的后面.但函数声明会吧优先权让给变量声明.但是经过变量初始化你将会得到不同的结果
function value(){
    return 1;
}
var value = 1;
alert(typeof value);    //"number"
因为value = 1变量赋值的时候又覆盖了 函数声明 所以变成了1

回归到咱们的测试题 其实可以简化成下面这样:
var a = 1,
    b = function(x) {
        x && b(--x);
    };
alert(a);
显而易见 就是弹出1

第三题

function a(x) {
    return x * 2;
}
var a;
alert(a);
如果理解了前面的两个实例那么这个就很容易理解了.var a;作用域被提前 然后函数a将其覆盖. 由于没有a变量赋值, 所以最后弹出了整个函数的source

第四题

function b(x, y, a) {
    arguments[2] = 10;
    alert(a);
}
b(1, 2, 3);
这个例子在所有浏览器里都显示10.
原因.首先放上ECMA对arguments的说明.
ECMA-262, 3rd Edition, section 10.1.8 says about an arguments object:

For each non-negative integer, arg, less than the value of the length property, a property is created with name ToString(arg) and property attributes { DontEnum }. The initial value of this property is the value of the corresponding actual parameter supplied by the caller. The first actual parameter value corresponds to arg = 0, the second to arg = 1, and so on. In the case when arg is less than the number of formal parameters for the Function object, this property shares its value with the corresponding property of the activation object. This means that changing this property changes the corresponding property of the activation object and vice versa.

尤其最后这一句
This means that changing this property changes the corresponding property of the activation object and vice versa.
当arguments的属性值改变那么活动对象的对应属性也跟着变.反之亦然.
简而言之就是arguments的属性和相对性对象的属性 是值共享的 两者总是保持着相同的值.

所以由于arguments[2] = 10了 所以对应的活动对象属性也为10.

第五题

function a() {
    alert(this);
}
a.call(null);
这个其实理解起来没那么难.我们需要了解两个知识点.
1) 应该理解this的值是怎么确定的.当一个对象的方法被执行.this就指向该方法的拥有者这个对象.如
var object = {
    method: function() {
        alert(this === object);    //true
    }
}
object.method(); 
在上面的代码里.当object.method()被执行时.this最终指向object.在全局环境里this指向window(当然如果非浏览器对象就指向默认的宿主).所以当一个函数不属于一个对象的属性是 那么this就等于window
function method() {
    alert(this === window);    //true
}
method(); 
上面的this就指向了全局的对象 window.

2) 有了(1)的知识做基础.我们再需要的就是知道第二个重要的点.call做了什么.call()方法执行函数.比如另一个对象的方法. 这个方法的this将被call的第一个函数代替,然后其余的参数就按顺序传入到那个方法中.
function method() {
    alert(this === window);
}
method();    //true
method.call(document);   //false
此时call是method内部的this指向了document所以返回false.
**An interesting part of ECMA-262, 3rd edition describes what should happen when null is passed in as the first argument to call():

If thisArg is null or undefined, the called function is passed the global object as the this value. Otherwise, the called function is passed ToObject(thisArg) as the this value.
所以call(或者apply)如果传入null.将默认为全局对象.即浏览器的window或者其它的宿主环境.所以例子可以改写为:
function a() {
    alert(this);
}
a.call(window);
这样结果就会显示window.

转载于:https://www.cnblogs.com/linpengfeixgu/articles/1658380.html

javascript谜题相关推荐

  1. 算法谜题 php,JavaScript实现N皇后问题算法谜题解答_javascript技巧

    谜题 N皇后问题.将N个皇后放置在NxN的国际象棋棋盘上,其中没有任何两个皇后处于同一行.同一列或同一对角线上,以使得它们不能互相攻击. 策略 回溯法. JavaScript解 以8皇后问题为例: 代 ...

  2. JavaScript,25 岁生日快乐!

    1995 年 12 月 4 日,网景和 Sun 发表了一份联合声明,宣布推出 JavaScript.它是一种开放的.跨平台的.易于使用的对象脚本语言,用于在企业网络和互联网上实时创建和定制应用程序.历 ...

  3. php网页无痕预览,javascript,html5_如何应对用户使用无痕浏览模式,javascript,html5 - phpStudy...

    如何应对用户使用无痕浏览模式 在开发过程中,由于一些页面会使用localStorage,sessionStorage ,在无痕浏览模式,本地存储不能用,会出现很多问题,看到过一种解决方案 functi ...

  4. 从事编程十年的程序员深谈JavaScript函数式

    在故事开始之前,我已经是一个拥有 10 年以上经验的专业程序员.先是 C++,然后是 C#,再然后是 Python.我能够写各种代码,我对模式和原则的掌握程度已经让我自信到看不到有学习新东西的必要.我 ...

  5. Python、JavaScript、Go、Linux学习资料总结

    Python 因为对Python还蛮感兴趣的,所以总结一下Python学习资料,包括三部分: 可以学习Python的地方:如果你也想学Python的话,那么可以在这些地方进行学习: Python可以做 ...

  6. 【AJAX】JavaScript的面向对象

    Ajax中后端数据返回后需要前端通过JavaScript来实现动态数据更新的问题.所以,在Ajax中加深了一遍JavaScript面向对象的印象. 基础部分: JavaScript中创建对象并简单对象 ...

  7. 【JavaScript总结】JavaScript语法基础:JS高级语法

    作用域链: 1.JS中只有函数能够限定作用域的范围: 2.变量处理在制定的函数范围内,还有一个特殊的作用域,就是没有用var 声明的全局作用域 3.js中的作用域链是为了清晰的表示出所有变量的作用范围 ...

  8. 【JavaScript总结】JavaScript语法基础:DOM

    ->DOM的理解:文档对应dom树 ->有了DOM能做什么:DOM的操作 html文档做为DOM树模型,DOM树的节点就是对象.对象会触发事件来执行一些事件代码. C#中的事件是一个委托变 ...

  9. 【JavaScript总结】JavaScript语法基础:JS编码

    运算符 数学:+. -. *. / 逻辑:>. < .>= .<=. == . !=.&&.|| . === .!==(完全等于) 对象相关 new delet ...

最新文章

  1. Spring Cloud下微服务权限方案
  2. Vmware虚拟机的复制后无法使用的问题和解决
  3. 如何制作一颗CPU? 从石子到管脚绑定
  4. 2021年春季学期-信号与系统-第四次作业参考答案-第二小题
  5. SpringBoot中对thymeleaf的时间进行格式化显示
  6. springboot2.3.4集成EhCache缓存框架完整代码
  7. 【Xamarin开发 Android 系列 12】 创建一个Json读取数据应用-添加定位服务
  8. allan方差 imu_MEMS-IMU随机误差的Allan方差分析
  9. Error: Current license file does not support the EP1C6Q240C8/EP3C10E144C8 device
  10. 计算机设置了分组用户怎么切换,怎么弄微信小号-不单止换小号,另外这些微信小技巧也一定让你“相见恨晚”...
  11. Revisiting ResNets: Improved Training and Scaling Strategies论文简述
  12. matlab 交换两列数据,在MATLAB单元阵列的两列中列出单元格内容(List cell contents in two columns of MATLAB cell array)...
  13. jQery 日历 带农历显示
  14. 软件测试—第五章白盒测试.逻辑覆盖法
  15. Python软件编程等级考试二级——20220618
  16. DCOS之k8s的secret
  17. 圆角矩形 shader
  18. 2021-07-09 终值定理和稳态误差【自动控制原理】
  19. LTE网络中UU与X2接口研究
  20. 旧款 mac 电脑重装 OS X Lion 10.7.5 系统的 U 盘安装盘制作及遇到问题和解决方法

热门文章

  1. android 打印机打印html,Android下通过wifi调用打印机打印
  2. python获取渲染之后的网页_Phantomjs抓取渲染JS后的网页(Python代码)
  3. python基础类型,Python基础-类
  4. 表格缓存问题_缓存常见问题,一网打尽哦!
  5. git checkout 命令详解
  6. 《Linux内核分析》课程总结
  7. android 进程间的通信,Android native进程间通信实例-binder结合共享内存
  8. C++11构造与禁用默认函数
  9. c语言链表查找的代码与题目,链表的C语言实现之单链表的查找运算_c语言
  10. x265-确定slice type-3