l 在 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 规范时定了三个原则:
- 把所有与浏览器相关的代码全部删掉;
- 全面支持 Unicode 编码;
- 要求对象和平台无关;
其中第二条原则,全面支持 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 中都成了关键字。
为了避免自己的变量命名和关键字或保留字产生冲突,可以采用以下几种方法:
- 可以把关键字都记住,另外,在 JS 中所有 Java 的关键字都是保留字,所以熟悉 Java 的同学记住保留字也没压力啦。
- 因为关键字和保留字都是使用小写字母,所以可以采用驼峰式命名自己的变量。
- 使用拼音命名自己的变量,虽然看起来不那么高级,但是据说很多人这样用。
关于变量
当你给一个变量赋值时,并不会把它标记为特定的数据类型,但你使用 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 会动态地去查找这个变量的类型。
这篇笔记是对喜马拉雅上沙翼老师的#陪你读书#教程第三期的记录总结。