真正理解javascript的五道题目.
题目一:
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
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("a" in window);
var a;
此时,尽管声明是在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。
提前这个词语显得有点迷惑了,你可以理解为:预编译。
题目2
var a = 1,
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了。
题目3
function a() {
return 1 ;
}
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 对象
题目5
function a() {
alert(this);
}
a.call(null);
这个题目可以说是最简单的,也是最诡异的!关于这个题目,我们先来了解2个概念。
这个问题主要考察 Javascript 的 this 关键字,具体看这里:
关于 a.call(null); 根据ECMAScript262规范规定:如果第一个参数传入的对象调用者是null或者undefined的话,call方法将把全局对象(也就是window)作为this的值。所以,不管你什么时候传入null,其this都是全局对象window,所以该题目可以理解成如下代码:
function a() {
alert(this);
}
a.call(window);
所以弹出的结果是[object Window]就很容易理解了。
—————
总结:
这5个题目虽然貌似有点偏,但实际上考察的依然是基本概念,只有熟知了这些基本概念才能写出高质量代码。
真正理解javascript的五道题目.的更多相关文章
- 深入理解javascript原型和闭包(8)——简述【执行上下文】上
什么是“执行上下文”(也叫做“执行上下文环境”)?暂且不下定义,先看一段代码: 第一句报错,a未定义,很正常.第二句.第三句输出都是undefined,说明浏览器在执行console.log(a)时, ...
- 深入理解JavaScript系列(20):《你真懂JavaScript吗?》答案详解
介绍 昨天发的<大叔手记(19):你真懂JavaScript吗?>里面的5个题目,有很多回答,发现强人还是很多的,很多人都全部答对了. 今天我们来对这5个题目详细分析一下,希望对大家有所帮 ...
- 全方位深入理解JavaScript面向对象
JavaScript面向对象程序设计 转载:https://blog.csdn.net/lihangxiaoji/article/details/79753473#72__871 本文会碰到的知识点: ...
- 深入理解javascript原型和闭包 (转)
该教程绕开了javascript的一些基本的语法知识,直接讲解javascript中最难理解的两个部分,也是和其他主流面向对象语言区别最大的两个部分--原型和闭包,当然,肯定少不了原型链和作用域链.帮 ...
- 深入理解JavaScript运行机制
深入理解JavaScript运行机制 前言 本文是写作在给团队新人培训之际,所以其实本文的受众是对JavaScript的运行机制不了解或了解起来有困难的小伙伴.也就是说,其实真正的原理和本文阐述的并不 ...
- 深入理解javascript系列(4):立即调用的函数表达式
本文来自汤姆大叔 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行. 在详细了解这个之前,我们来谈了解一下“自执行”这个叫法,本文对这个功能的叫法 ...
- 深入理解javascript原型和闭包系列
从下面目录中可以看到,本系列有16篇文章,外加两篇后补的,一共18篇文章.写了半个月,从9月17号开始写的.每篇文章更新时,读者的反馈还是可以的,虽然不至于上头条,但是也算是中规中矩,有看的人,也有评 ...
- 深入理解JavaScript的闭包特性如何给循环中的对象添加事件
初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...
- 深入理解javascript原型和闭包(1)——一切都是对象
“一切都是对象”这句话的重点在于如何去理解“对象”这个概念. ——当然,也不是所有的都是对象,值类型就不是对象. 首先咱们还是先看看javascript中一个常用的函数——typeof().typeo ...
随机推荐
- android的animator
3.0 以前,android支持两种动画模式,tween animation,frame animation,在android3.0中又引入了一个新的动画系统:property animation,这 ...
- arm:启动代码判断是从nand启动还是从norflash启动,拷贝程序到内存的过程
一.nand启动和nor启动:[1] CPU从0x00000000位置开始运行程序. 1.nand启动: 如果将S3C2440配置成从NANDFLASH启动(将开发板的启动开关拔到nand端,此时OM ...
- 网页制作之html基础学习6-CSS浏览器兼容问题
初学html和css时,每天切图,总会遇到很多浏览器兼容性问题.最近一直关注移动平台开发,就html和css来说,不用考虑那么多浏览器兼容性问题.到现在,以至于很多浏览器兼容性几乎忘光了.今天把以前总 ...
- Android:Notification的生成与取消
MainActivity.java: package com.example.notificationdemo; import android.app.Activity; import android ...
- 使用SHA1、SHA2双证书进行微软数字签名
微软是第一个宣布了SHA-1弃用计划,在2016年之后Windows和IE将不再信任SHA-1证书.正好我们公司的数字签名也到期了,索性就重新申请了sha256和sha1的新数字证书,用来给产品签名. ...
- AlphaMobileControls介绍
大家在开发wince程序或者windows mobile程序时还在为丑陋的界面着急吗?AlphaMobileControls可以帮你解决这些方案.当然如果你是高手可以自己去实现一些特殊的功能,自己定义 ...
- 【译】在Asp.Net中操作PDF – iTextSharp - 操作图片
原文 [译]在Asp.Net中操作PDF – iTextSharp - 操作图片 作为我的iTextSharp系列的文章的第七篇,开始探索使用iTextSharp在PDF中操作图片,理解本篇文章需要看 ...
- 基于visual Studio2013解决C语言竞赛题之0609矩阵处理
题目
- GoldenGate配置(二)之双向复制配置
GoldenGate配置(二)之双向复制配置 环境: Item Source System Target System Platform Red Hat Enterprise Linux Serve ...
- static在C和C++中的用法和区别
static主要有三个作用: (1)局部静态变量 (2)外部静态变量/函数 (3)静态数据成员/成员函数 前两种C和C++都有,第三种仅在C++中有,下面分别作以下介绍: 一.局部静态变量 在C/C+ ...