在 JS 中区分大小写

l  把 JS 写到 HTML 里会有什么问题?

l  HTML 中的 data-*

l  关于变量名

l  如何注释代码?

l  严格模式是什么?

l  JS 解释器自动加分号原则

l  关键字和保留字

l  关于变量

l  小结

 

在 JS 中区分大小写


 

JS 是区分大小写的,也就是说 foo 和 Foo 是两个完全不同的标识符,这个大家都清楚,但要注意的一点是,一般来说,JS 都是与 HTML 和 CSS 一起使用的,而后两者是不区分大小写的。虽然 HTML 规范中要求浏览器厂商对 HTML 中的大小写作规范,但所有浏览器在处理页面逻辑时都会对大小写做兼容工作,也就是说不区分大小写。

 

把 JS 写到 HTML 里会有什么问题?


 

一般来说,往页面中插入 JS 最常用的方法是使用 <script> 标签,但也可以直接把 JS 代码写到 HTML 中,一般是 HTML 事件,如

<span onclick=”alert(“Hello World!”);”>Click!</span>

如果是像这样把 onclick 作为 HTML 的属性来运行,那么这个属性名可以写作是 onClick, Onclick, OnClick, oNcliCk等等都可以(当然,一般建议用小写字母),但这说明了 HTML 是不区分大小写的。但是,如果在 JS 中写这个事件处理程序,那就必须使用小写的 onclick,写成其他形式一律报错。另外,虽然 HTML 不区分大小写,但是引号里的 JS 代码还是区分大小写的,也就是上面的 onclick= 后面的引号里的内容  alert(“Hello World!”);,如果写成了 Alert(“Hello World!”); 也是会报错的。

 

HTML 中的 data-*


 

data-* 是支持 key-value 结构的,可以给某个元素添加一个自定义属性如 data-name=”suki”。 data-* 里 * 的内容必须是小写的,即使使用了大写字母,也会被自动转换成小写,也就是说,即使你写了 data-Name=”suki” 或者 data-NAME=”suki”,最终都会被转换成 data-name=”suki”。如果你添加属性时使用了大写字母,然后需要在 JS 中获取这个属性的话,还是需要使用小写的属性名,如果使用 dataset API 时是用了大写字母,是取不到你想要的属性值的。但是奇怪的是,如果用 getAttribute() 这个函数来取值的话,就不区分大小写了。

<body>
    <p data-Name="suki" id="suki">suki</p>

    <script>
        var suki = document.querySelector('#suki');

        var name = suki.getAttribute("data-Name");  // suki

        var name = suki.getAttribute("data-NAme");  // suki

        var name = suki.dataset.name;  // suki

        var name = suki.dataset.Name;  // undefined
    </script>
</body>

 

JQuery 提供了一个 data() 函数,接收两个参数key和value,当你使用 data(key, value) 存值的时候 key 可能是大小写混合的,但是当你使用 data(key) 去取这个值的时候如果还使用大小写混合的 key,就很有可能取不到这个值,或者是取到一个错误的值。所以一定要注意,无论存值的时候 key 是大写或小写都好,取值的时候一定要用小写。当然,最好还是不要在 data-* 结构中使用大写字母。

 

关于变量名


 

标识符,就是指变量、函数的名字,以字母、_、$为第一个字符,其中字母可以是任何一门语言的文字。

 

ECMAScript 当初在定 JS 规范时定了三个原则:

  1. 把所有与浏览器相关的代码全部删掉;
  2. 全面支持 Unicode 编码;
  3. 要求对象和平台无关;

其中第二条原则,全面支持 Unicode 编码,说明我们可以在 JS 中使用任意一门语言,也就是我们也可以用汉字为变量命名。但是因为全角与半角符号切换的问题不推荐使用汉字作为标识符。

 

如何注释代码?


 

//单行注释


/*

*  块级注释

*  块级注释

*  块级注释

*/

除了前后两行,块级注释中间行的 * 是没有必要的,加上只是为了美观,提高可读性。但是没有必要手写这种格式的注释,很多编辑器都带有代码注释插件。

 

严格模式是什么?


 

ECMAScript3 中有一些不合理的地方,导致代码在浏览器中运行时可能会出现一些无法解释的怪异现象。为了解决这些问题,ECMAScript5 在 JS 中增加了一个标志, ”use strict”; ,这看起来像是一个字符串,但实际上是一个标志,用来告诉浏览器,如果碰到了这个标志,则以一种更严格的方式来执行 JS 代码。

 

有两种方法可以开启严格模式,第一种是把 ”use strict”; 写在整个代码的第一行,表示以下所有的代码都是以严格模式来执行;第二种是把它写在函数体的第一行,表示只有这个函数体里面的代码是以严格模式执行。

 

把 ”use strict”; 写在整个代码的第一行可能会出现的问题是,在代码合并的时候,如果代码文件1是正常模式的,代码文件2是严格模式的,那么两者按1、2顺序合并后,代码会以正常模式执行,因为这是 ”use strict”; 不处于整个代码的第一行了,所以开启严格模式失败;如果两者是按2、1的顺序合并的,或者在引入 JS 文件时文件2在文件1之前引入,这时整个代码都会以严格模式执行,而正常模式的代码如果放到严格模式下去执行,可能有很多地方会出问题,如严格模式会禁止隐式声明全局变量。

 

所以通常情况下,我们会把严格模式的代码放到一个匿名函数里运行。如果你想尝试使用严格模式,建议先试着在函数中使用,而不是对整个代码使用严格模式。

 

如果代码中使用了严格模式,想要在控制台测试代码可能会遇到问题,因为有些浏览器的控制台是基于 eval() 函数执行的,如果把一段严格模式的代码粘贴到控制台,浏览器会把这段代码放到 eval() 函数里,这时候 ”use strict”; 就不再是代码的第一行了,所以严格模式启动失败,代码会按正常模式执行。所以如果想要调试严格模式的代码,最好是 JS 代码放到单独的页面中,不要在浏览器的控制台中测试。其实有很多细小的错误在控制台里是调不出来的,一定要把代码写在页面中保存起来再去测试。

 

现代浏览器以及 IE10+ 都是支持严格模式的,如果遇到不支持严格模式的浏览器,那 ”use strict”; 会被忽略掉,但是可能会导致运行结果与严格模式下的运行结果不一致。

 

JS 解释器自动加分号原则


 

JS 解释器如果碰到不带分号的代码,它会先判断后一行代码能不能与这一行代码合并执行,如果可以,就把两行代码合并;如果不可以,就在这一行的末尾加一个分号;如果加了分号还不能执行,那就报错。

 

JS 解释器处理不带分号的语句的原则导致的问题是,如果某一行代码不以分号结尾,而下一行代码以花括号或运算符开头,这两行代码很有可能会合并起来执行,这样做的好处是,当我们使用条件判断语句的时候,如果条件太多,写在同一行的话看起来有点麻烦,这时候我们可以把条件分行写。坏处是,如果下一行代码以花括号开头,那两行代码合并可能就变成了一个函数,与你的预期结果可能会不一样。在与其他人的代码合并时,如果想避免这种情况,可以在你的代码开头加一个分号,这是很多程序员的做法,避免别人的代码中漏了分号导致自己的代码无法正常执行的情况。

 

虽然刚刚说 JS 解释器如果碰到不带分号的代码时能合并就合并执行,但是还是有例外情况的,当它碰到 return、break、continue 这三个关键字的时候,会直接把代码结束掉,完全不理会下一行的代码是什么内容。尤其是在使用 return 语句的时候,不要把返回值换行写,否则解释器会忽略它,直接返回 undefined,而且这种情况很难 debug,因为没有语法错误,浏览器不会报错,虽然某些编辑器可能会有提醒。

 

第二个例外的情况,判断一下以下代码会输出什么?

a = 1
b = 2
a
++
b

console.log(a, b)

按解释器“能合并就合并”的原则 ++ 应该是与 a 合并,但是自增和自减运算符是一个例外,它们会和下一行代码合并,所以以上代码相当于:

a = 1;
b = 2;
a;
++b;

console.log(a, b); // 1 3

 

关键字和保留字


 

下面这两个表格只是为了方便我自己看的。

 

关键字

break

case

catch

continue

debugger

default

delete

do

else

finally

for

function

if

in

instanceof

new

return

switch

this

throw

try

typeof

var

void

while

with

 

 

 

 

 

 

第5版保留字

非严格模式

class

const

enum

export

extends

import

super

 

 

 

严格模式

implements

interface

let

package

private

protected

public

static

yield

 

第5版保留字中有许多在 ES6 中都成了关键字。

 

为了避免自己的变量命名和关键字或保留字产生冲突,可以采用以下几种方法:

  1. 可以把关键字都记住,另外,在 JS 中所有 Java 的关键字都是保留字,所以熟悉 Java 的同学记住保留字也没压力啦。
  2. 因为关键字和保留字都是使用小写字母,所以可以采用驼峰式命名自己的变量。
  3. 使用拼音命名自己的变量,虽然看起来不那么高级,但是据说很多人这样用。

 

关于变量


 

当你给一个变量赋值时,并不会把它标记为特定的数据类型,但你使用 typeof 去查询变量的类型时,会动态地去取这个之前保存的那个值的类型。

 

定义变量时,使用 var 定义的是局部变量,不使用 var 的则是全局变量。

 

可以使用一个 var 关键字声明多个变量:

var a = 1,
    b = 2,
    c = 3;

但上面这种结构不推荐,容易忘记加逗号,可以改成:

var a = 1
   ,b = 2
   ,c = 3;

这样可以避免忘记加逗号所造成的问题。

 

小结


 

JS 是区分大小写,与不区分大小写的 HTML 混用时可能会产生一些问题。使用data-* 时也要注意大小写问题。JS 中的标识符可以使用字母、_、$,其中字母不仅指英文字母,我们还可以使用拼音、汉字或者其他语言文字。JS 有两种注释方法,单行注释和块级注释。在整个代码第一行或在函数内第一行输入 ”use strict”; 可以开启严格模式,严格模式与标准模式在变量声明等方面有一些不同,可以先尝试在函数内使用严格模式。JS 解释器自动加分号的原则是能合并的代码就合并起来执行,但是也存在例外。建议写 JS 该加的括号和分号不要落下,不然可能会出现与自己预期不同的结果。自己声明变量时要注意标识符不能与 JS 的关键字和保留字一样。在 JS 中声明变量并给它赋值并不会规定变量的类型,使用 typeof 之所以能查到变量类型,是因为使用 typeof 时 JS 会动态地去查找这个变量的类型。

 

这篇笔记是对喜马拉雅上沙翼老师的#陪你读书#教程第三期的记录总结。