本文总结了JS在日常使用和面试中需要注意的知识点。
变量提升
请看以下代码输出什么
1 | showName() |
答案:
答案和我们印象中js自上而下的执行顺序有些出入,这是由于js为了开发者写代码方便而省略掉的变量声明部分,而在编译阶段会将此部分补充完整,而开发者习惯了“简洁版”,并延续了”简洁版”的思路而产生的错觉。
现在,我们把”省去”的声明代码还原,就能发现端倪:
首先看变量的“全貌”:
var myname = 'hello world'
1 | var myname //声明部分 |
再看看函数的“全貌”:
1 | // 把声明提前 |
在这里,以上函数showName
是一个完整的函数声明,没有赋值操作,而如下函数声明,是声明与赋值分开的:
1 |
|
等同于如下操作:
1 | // 声明 |
所谓的变量提升,是指在 JavaScript 代码执行过程中,JavaScript 引擎把变量的声明部分和函数的声明部分提升到代码开头的“行为”。变量被提升后,会给变量设置默认值,这个默认值就是我们熟悉的 undefined。
script标签
请看以下代码,将输出什么?
1 | <script type="text/javascript"> |
答案:程序报错
包含在<script>标签的内容,将会被浏览器顺序执行,直到遇到</script>;特别注意:不要在代码的任何地方出现“</script>”字符串,只要一出现,浏览器的解释器就认为是代码终止符到了,后续内容将不再解析;应该换为“<\/script>”,这样浏览器会对内容做一个转义,程序就能正常运行了。
undefined
JS整个语言只有六种数据类型:undefined、Null、Boolean、Number、String以及Object,JS不支持自定义类型的机制。
请看以下代码,试问返回什么
1 |
|
答案显而易见:在进行alert(age)
的时候,报错了;那再看看如下代码,请问会输出什么:
1 | var message |
答案可能很意外,会弹出两次undefined
,而且不报错。
可能让人感到很奇怪,但事实却是如此;对未初始化的变量进行typeof
操作符会返回undefined
的,对未定义的变量进行typeof
操作也是会返回undefined
;可能背后的逻辑是:无论变量是否定义,都不会真正执行吧
NaN
请看以下代码输出什么?
1 | console.log(NaN === NaN) |
正确答案是:false
NaN的含义是:“Not a Number”;是一个特殊的值,这个数值表示一个本来返回数值的操作数未返回数值的情况,以替代直接报错。例如:“10 / 0” 在其他语言中直接就报错了,但是JS为了防止程序报错崩溃,加入了NaN
,10 / 0 = NaN
,NaN与任何数操作都是NaN,例如:NaN * 10会返回NaN。有人会问,那我判断一个变量值是否是NaN该如何做呢?其实JS提供了内置函数isNaN()
函数参数
请看以下代码输出什么?
1 | function sum(num1, num2){ |
会报错吗?
正确答案是:输出NaN
js函数的参数与绝大多数语言中的参数不同,js对函数参数的类型和个数都没有强制限制;在js内部,函数参数的实现是拿一个数组来表示的;因此,哪怕你定义了两个参数,只传进去一个参数,也不影响js的正常运行。
写代码的时候,在js的函数体内部,可以通过arguments对象来访问js的参数数组,从而获取传递给函数的每一个参数。
再来看看以上这道题目,sum
函数有俩参数,但是只传了一个参数,程序不会报错,原因不解释了。在sum
函数中,程序变为了 1 + arguments[1],由于 arguments[1]为传参,故值为undefined
, 1 + undefined
为NaN
(not a number)
函数名
请看以下代码,存在两个相同的函数名,在代码运行后,会输出什么?
1 | function addNum(num) { |
正确答案:输出21
其他语言中例如Java,只要定义函数签名或者函数参数类型和数量不同,就可以定义相同的函数名,这是传统意义上的重载,但是JS中没有重载,如果定义了两个以上相同的函数名,JS最终会以最后定义的函数为准。
变量
请看一下代码,最终会输出什么?
1 | var num1 = 5 |
正确答案:
1 | 5 |
js的变量值可分为:基本类型
和引用类型
两种;其中,基本类型
值是简单的数据段,包含 underfined
、Null
、Boolean
、Number
和String
这五种,其余为引用类型。
这两种类型的值在进行变量间赋值的时候,也会有所不同。对于值是基本类型
的变量,在赋值的时候,会在给赋值变量复制一个新值。例如上题中的var num2 = num1
这时,是将num1的值复制一份,填写给num2
,相当于:var num2 = 5
。
但是,如果是引用类型
的变量,在赋值的时候,各种变量还会指向原引用。例如代码中的var obj2 = obj1
,此时obj2
和obj1
同时指向了同一个object。