JS的那些坑

Posted 菜刚

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS的那些坑相关的知识,希望对你有一定的参考价值。

本文总结了JS在日常使用和面试中需要注意的知识点。

变量提升

请看以下代码输出什么

    showName()
    console.log(myname)
    var myname = 'hello world'
    function showName()  
        console.log('函数showName被执行')
    

答案

答案和我们印象中js自上而下的执行顺序有些出入,这是由于js为了开发者写代码方便而省略掉的变量声明部分,而在编译阶段会将此部分补充完整,而开发者习惯了“简洁版”,并延续了”简洁版”的思路而产生的错觉。
现在,我们把"省去"的声明代码还原,就能发现端倪:

首先看变量的“全貌”:

var myname = 'hello world'

    var myname //声明部分
    
    myname = 'hello world' //赋值部分

再看看函数的“全貌”:

// 把声明提前
function showName()  
   console.log('函数showName被执行')


//执行部分
showName()

在这里,以上函数showName是一个完整的函数声明,没有赋值操作,而如下函数声明,是声明与赋值分开的:


var showName = function()
    console.log("函数showName被执行")

等同于如下操作:

// 声明
var showName = undefined

// 赋值
showName = function()
    console.log("函数showName被执行")

所谓的变量提升,是指在 javascript 代码执行过程中,JavaScript 引擎把变量的声明部分和函数的声明部分提升到代码开头的“行为”。变量被提升后,会给变量设置默认值,这个默认值就是我们熟悉的 undefined。

script标签

请看以下代码,将输出什么?

<script type="text/javascript">
    console.log("1")
    console.log("</script>")
    console.log("2")
</script>

答案:程序报错

包含在<script>标签的内容,将会被浏览器顺序执行,直到遇到</script>;特别注意:不要在代码的任何地方出现“</script>”字符串,只要一出现,浏览器的解释器就认为是代码终止符到了,后续内容将不再解析;应该换为“<\\/script>”,这样浏览器会对内容做一个转义,程序就能正常运行了。

undefined

JS整个语言只有六种数据类型:undefined、Null、Boolean、Number、String以及Object,JS不支持自定义类型的机制。

请看以下代码,试问返回什么


var message

alert(message)
alert(age)

答案显而易见:在进行alert(age)的时候,报错了;那再看看如下代码,请问会输出什么:

var message

alert(typeof message)
alert(typeof age)

答案可能很意外,会弹出两次undefined,而且不报错。

可能让人感到很奇怪,但事实却是如此;对未初始化的变量进行typeof操作符会返回undefined的,对未定义的变量进行typeof操作也是会返回undefined;可能背后的逻辑是:无论变量是否定义,都不会真正执行吧

NaN

请看以下代码输出什么?

console.log(NaN === NaN)

正确答案是:false

NaN的含义是:“Not a Number”;是一个特殊的值,这个数值表示一个本来返回数值的操作数未返回数值的情况,以替代直接报错。例如:“10 / 0” 在其他语言中直接就报错了,但是JS为了防止程序报错崩溃,加入了NaN10 / 0 = NaN,NaN与任何数操作都是NaN,例如:NaN * 10会返回NaN。有人会问,那我判断一个变量值是否是NaN该如何做呢?其实JS提供了内置函数isNaN()

函数参数

请看以下代码输出什么?

function sum(num1, num2)
    return num1 + num2


let a = sum(1)
console.log(a)

会报错吗?
正确答案是:输出NaN

js函数的参数与绝大多数语言中的参数不同,js对函数参数的类型和个数都没有强制限制;在js内部,函数参数的实现是拿一个数组来表示的;因此,哪怕你定义了两个参数,只传进去一个参数,也不影响js的正常运行。
写代码的时候,在js的函数体内部,可以通过arguments对象来访问js的参数数组,从而获取传递给函数的每一个参数。

再来看看以上这道题目,sum函数有俩参数,但是只传了一个参数,程序不会报错,原因不解释了。在sum函数中,程序变为了 1 + arguments[1],由于 arguments[1]为传参,故值为undefined, 1 + undefinedNaN(not a number)

函数名

请看以下代码,存在两个相同的函数名,在代码运行后,会输出什么?

function addNum(num) 
     return num + 10


function addNum(num) 
    return num + 20


let num = addNum(1)
console.log(num)

正确答案:输出21

其他语言中例如Java,只要定义函数签名或者函数参数类型和数量不同,就可以定义相同的函数名,这是传统意义上的重载,但是JS中没有重载,如果定义了两个以上相同的函数名,JS最终会以最后定义的函数为准。

变量

请看一下代码,最终会输出什么?

    var num1 = 5
    var num2 = num1
    num2 = num2 + 1
    console.log(num1)


    var obj1 = new Object()
    var obj2 = obj1
    obj2.name = "ryugou"
    console.log(obj1.name)

正确答案:

    5
    ryugou

js的变量值可分为:基本类型引用类型两种;其中,基本类型值是简单的数据段,包含 underfinedNullBooleanNumberString这五种,其余为引用类型。
这两种类型的值在进行变量间赋值的时候,也会有所不同。对于值是基本类型的变量,在赋值的时候,会在给赋值变量复制一个新值。例如上题中的var num2 = num1这时,是将num1的值复制一份,填写给num2,相当于:var num2 = 5
但是,如果是引用类型的变量,在赋值的时候,各种变量还会指向原引用。例如代码中的var obj2 = obj1,此时obj2obj1同时指向了同一个object。

更多精彩内容,请关注我的公众号

以上是关于JS的那些坑的主要内容,如果未能解决你的问题,请参考以下文章

JS的那些坑

JS的那些坑

读了这一篇,让你少踩 ArrayList 的那些坑

读了这一篇,让你少踩 ArrayList 的那些坑

Ember.js的那些坑

微信小程序 网络请求之re.request 和那些坑