`
wangshaofei
  • 浏览: 283564 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

你真的已经搞懂JavaScript了吗

    博客分类:
  • js
 
阅读更多

题目一:

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 关键字,具体看这里:
关于Javascript语言中this关键字的用法www.2cto.com
关 于 a.call(null); 根据ECMAScript262规范规定:如果第一个参数传入的对象调用者是null或者undefined的话,call方法将把全局对象(也就是 window)作为this的值。所以,不管你什么时候传入null,其this都是全局对象window,所以该题目可以理解成如下代码:
function a() {
    alert(this);
}
a.call(window);
所以弹出的结果是[object Window]就很容易理解了。
—————
总结:
这5个题目虽然貌似有点偏,但实际上考察的依然是基本概念,只有熟知了这些基本概念才能写出高质量代码
分享到:
评论

相关推荐

    参加JavaScript面试,必须搞懂的问题(推荐)

    JavaScript是Web开发中不可或缺的一部分,尤其在面试中,掌握其核心概念是至关重要的。本文将深入探讨JavaScript中的一些关键知识点,包括对象、函数以及它们在实际应用中的使用方式。 首先,我们来了解一下...

    JavaScript你一定要搞懂的原型链

    内容概要:在 JavaScript 中,每个对象都有一个原型。当访问一个对象的属性或方法时,如果对象本身没有定义该属性或方法,JavaScript 就会沿着原型链向上查找,直到找到该属性或方法或者到达原型链的末尾(null)...

    【JavaScript源代码】一文搞懂TypeScript的安装、使用、自动编译的教程.docx

    TypeScript是一种由微软开发的开源、跨平台的编程语言,它是JavaScript的超集,意味着所有合法的JavaScript代码都是合法的TypeScript代码。TypeScript的主要特点是提供了类型系统和对ES6及更高版本的支持,旨在帮助...

    JavaScript之ToDoList

    JavaScript的阶段性学习小作品: 功能一:JS实现在header中实时显示时间 功能二:JS实现按键监听事件与鼠标监听事件 功能三:JS实现从input输入框...结构简单,功能简单,前期学习小作品,大概新手几个小时就可以搞懂。

    javascript中this的指向问题总结

    JavaScript中this的指向还没搞明白?来这看看 你就懂啦~

    彻底搞懂JavaScript中的apply和call方法(必看)

    这里`this`是你希望设置的上下文对象,它可以是任何JavaScript对象。 在实际应用中,`apply`和`call`经常用来实现函数的继承和动态绑定。例如,在JavaScript面向对象编程中,当我们有一个`programmer`对象,其原型...

    愚人节-基于JavaScript的自动识别人脸并给头像戴上帽子、搞怪表情+源代码+文档说明

    基于JavaScript的自动识别人脸并给头像戴上帽子、搞怪表情 可自行修改增加搞怪表情 - 不懂运行,下载完可以私聊问,可远程教学 该资源内项目源码是个人的毕设,代码都测试ok,都是运行成功后才上传资源,答辩评审...

    彻底弄懂JavaScript中的this指向

    我们都知道 this是JavaScript 函数中的一个关键字,也称之为this对象,this是函数中的一个对象,那么这个对象表示什么呢,这个很重要,因我们会经常使用到这个this,如果搞不清楚这个this到底指向谁,就是很大的一个...

    关注基础知识,打造优质前端博客,公众号前端工匠的作者.zip

    作者目录努力打造一系列适合初级中级工程师能够看得懂的优质文章,今年博客关注于框架、TS和构建工具等基础原理分析,如果想第一时间获取文章,欢迎关注我的公众号工匠工匠,接走下去的路我们一起走...你还没有搞懂这个

    一个小例子搞懂分页

    JavaScript库如jQuery、Vue.js和React.js都有相应的分页组件,帮助开发者轻松实现前端分页效果。这些组件通常会处理页码的计算、请求数据以及显示数据等任务。 在工具方面,有些IDE(如IntelliJ IDEA)提供了数据库...

    详解帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)

    JavaScript中的`prototype`、`__proto__`和`constructor`是理解JavaScript面向对象编程的关键概念。这篇文章通过图解的方式深入浅出地解析了这三个概念之间的关系。 首先,`__proto__`属性是对象独有的,它指向对象...

    解javascript 混淆加密收藏

    直接手工解密,比想象中的要简单不少,花了不到半个小时就搞出来了。 Js解混淆最关键的部分: l eval或者[removed]、VBS的EXECUTE、execScript之类的可以运行js的函数 l unescape js的混淆一般有几种方法: 1. 把...

    JavaScript 不只是脚本

    认为一个脚本也没有太多的难度,那似乎为不懂程序的人专门设计的东西,不值得真正搞开发的去研究和应用。从LiveScript 到JavaScript,在大量的时间JS都只是作为一种Script脚本在应用。更多的开发者只有在前端表单...

    10个JavaScript中易犯小错误

    JavaScript的许多细节规定会让你的网页出现很多意想不到的bug,搞懂这些bug,对于成为一位有经验的JS开发者很重要。 常见错误一:对于this关键词的不正确引用 我曾经听一位喜剧演员说过: “我从未在这里,因为我不...

    Daotin#Web#06-一文搞懂DOM相关距离问题1

    一、问题由来刚开始学 DOM 操作中对于元素距离元素的距离问题总是迷迷糊糊的,虽然有万能的 getCurrentStyle 方式来取得所需要的属性,但是有时看别

    52讲轻松搞定网络爬虫.txt

    专栏从基础知识点讲起,通过样例代码,帮你搞懂基本用法和原理。每个知识点会结合实际案例,手把手带你进行爬虫实操,加深你对爬虫技术的理解。 学了这个专栏之后,你能轻松过掌握当下优秀爬虫所用到的必备技术,...

Global site tag (gtag.js) - Google Analytics