js复习基本概念(语法、严格模式)

1.语法

ECMAScript的语法大量借鉴了C及其他类C语言(如JAVA和Perl)的语法。

(1)区分大小写

  • ECMAScript中的一切(变量、函数名和操作符都区分大小写。

  • 拓展 HTML(要求区分大小写,但实际浏览器会做兼容)和CSS中不区分大小写

[1] js写在html中是否区分大小写

1
2
- 事件 如(onclick属性不区分大小写,但是事件后的内容区分大小写)
- 事件内的部分需要区分大小写 如:onclick="这部分"

[2] data属性

1
2
3
data写入属性都会转为小写 如: data-Name === data-name (chrome下测试并不是,ie下会有问题)

一旦涉及-都会涉及大小写问题,主要表现就是定义时如果存在大写,调用时需要用小写,负责会出现undefined

(2)标识符

所谓标识符,就是指变量、函数、属性的名字,或者函数的参数。

js中标识符是按下列格式规则组合起来的一或多个字符:

  • 第一个字符可以是:

    1
    (1)字母 (2)下划线(_)(3)美元符号($);
  • 其他字符可以是:

    1
    2
    (1)字母 (2)下划线 (3)美元符号 (4)数字
    // 汉字也是字符,unicode(不建议使用,除涉及数学计算)
  • ECMAScirpt推荐标识符采用驼峰大小写格式

(3) 注释

ECMAScirpt推荐标识符采用驼峰大小写格式使用C风格的注释

包含

  • [1] 单行注释
1
// 单行注释
  • [2] 多行注释
1
2
/*
 * 这是一个多行
* (块级注释) */

第二第三行的*不是必须的,纯粹为了提高可读性。

2.严格模式

ES5引入了严格模式(strict mode)

1
2
3
// 进入表示

"use strict";

老版本的浏览器会把它当作一行普通字符串,加以忽略。

“严格模式”有两种调用方法,适用于不同的场合。

[1] 启用(整个脚本启用)

将”use strict”放在脚本文件的第一行,则整个脚本都将以”严格模式”运行。如果这行语句不在第一行,则无效,整个脚本以”正常模式”运行。如果不同模式的代码文件合并成一个文件,这一点需要特别注意。

(严格地说,只要前面不是产生实际运行结果的语句,”use strict”可以不在第一行,比如直接跟在一个空的分号后面。)

1
2
3
4
5
6
7
8
 <script>
   "use strict";
   console.log("这是严格模式。");
 </script>

 <script>
   console.log("这是正常模式。");kly, it's almost 2 years ago now. I can admit it now - I run it on my school's network that has about 50 computers.
 </script>

[2] 启用(指定函数启用)

1
2
3
4
5
6
7
8
 function strict(){
   "use strict";
   return "这是严格模式。";
 }

 function notStrict() {
   return "这是正常模式。";
 }

[3] 脚本文件的变通写法

因为第一种调用方法不利于文件合并,所以更好的做法是,借用第二种方法,将整个脚本文件放在一个立即执行的匿名函数之中。

1
2
3
4
5
6
7
 (function (){

   "use strict";

   // some code here

 })();

[4] 严格模式目的

  • 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
  • 消除代码运行的一些不安全之处,保证代码运行的安全;
  • 提高编译器效率,增加运行速度;
  • 为未来新版本的Javascript做好铺垫。

[5] 语法和行为改变

(1) 全局变量显示声明

在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。

1
2
3
4
5
6
"use strict";

v = 1; // 报错,v未声明

for(i = 0; i < 2; i++) { // 报错,i未声明
}

因此,严格模式下,变量都必须先用var命令声明,然后再使用。

(2) 静态绑定

[1] 禁止使用with语句
因为with语句无法在编译时就确定,属性到底归属哪个对象。

1
2
3
4
5
6
7
 "use strict";

 var v = 1;

 with (o){ // 语法错误
   v = 2;
 }

[2] 创设eval作用域

1
2
3
正常模式下,Javascript语言有两种变量作用域(scope):全局作用域和函数作用域。严格模式创设了第三种作用域:eval作用域。

正常模式下,eval语句的作用域,取决于它处于全局作用域,还是处于函数作用域。严格模式下,eval语句本身就是一个作用域,不再能够生成全局变量了,它所生成的变量只能用于eval内部。

(3) 增强的安全措施

[1] 禁止this关键字指向全局对象

1
2
3
4
5
6
7
8
9
10
 function f(){
   return !this;
 }
 // 返回false,因为"this"指向全局对象,"!this"就是false

 function f(){
   "use strict";
   return !this;
 }
 // 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。

[2] 禁止在函数内部遍历调用栈

1
2
3
4
5
6
7
8
9
10
11
function f1(){

  "use strict";

  f1.caller; // 报错

  f1.arguments; // 报错

}

f1();

(4) 禁止删除变量

严格模式下无法删除变量。只有configurable设置为true的对象属性,才能被删除。

1
2
3
4
5
6
7
8
9
10
11
12
 "use strict";

 var x;

 delete x; // 语法错误

 var o = Object.create(null, {'x': {
     value: 1,
     configurable: true
 }});

 delete o.x; // 删除成功

(5) 显式报错

1
2
3
4
5
6
7
 "use strict";

 var o = {};

 Object.defineProperty(o, "v", { value: 1, writable: false });

 o.v = 2; // 报错

严格模式下,对一个使用getter方法读取的属性进行赋值,会报错。

1
2
3
4
5
6
7
8
9
 "use strict";

 var o = {

   get v() { return 1; }

 };

 o.v = 2; // 报错

(6) 重名错误

严格模式新增了一些语法错误。

(1)对象不能有重名的属性

正常模式下,如果对象有多个重名属性,最后赋值的那个属性会覆盖前面的值。严格模式下,这属于语法错误。

1
2
3
4
5
6
"use strict";

  var o = {
    p: 1,
    p: 2
  }; // 语法错误

(2)函数不能有重名的参数

正常模式下,如果函数有多个重名的参数,可以用arguments[i]读取。严格模式下,这属于语法错误。

1
2
3
4
5
6
7
 "use strict";

 function f(a, a, b) { // 语法错误

   return ;

}

(7) 禁止八进制表示法

正常模式下,整数的第一位如果是0,表示这是八进制数,比如0100等于十进制的64。严格模式禁止这种表示法,整数第一位为0,将报错。

1
2
3
 "use strict";

 var n = 0100; // 语法错误

(8) arguments对象的限制

arguments是函数的参数对象,严格模式对它的使用做了限制。

(1) 不允许对arguments赋值

1
2
3
4
5
6
7
8
9
10
11
  "use strict";

  arguments++; // 语法错误

  var obj = { set p(arguments) { } }; // 语法错误

  try { } catch (arguments) { } // 语法错误

  function arguments() { } // 语法错误

  var f = new Function("arguments", "'use strict'; return 17;"); // 语法错误

(2)arguments不再追踪参数的变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  function f(a) {

    a = 2;

    return [a, arguments[0]];

  }

  f(1); // 正常模式为[2,2]

  function f(a) {

    "use strict";

    a = 2;

    return [a, arguments[0]];

  }

  f(1); // 严格模式为[2,1]

(3)禁止使用arguments.callee

1
2
3
4
5
  "use strict";

  var f = function() { return arguments.callee; };

  f(); // 报错

(9) 函数必须声明在顶层

将来Javascript的新版本会引入”块级作用域”。为了与新版本接轨,严格模式只允许在全局作用域或函数作用域的顶层声明函数。也就是说,不允许在非函数的代码块内声明函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
  "use strict";

  if (true) {

    function f() { } // 语法错误

  }

  for (var i = 0; i < 5; i++) {

    function f2() { } // 语法错误

  }

(10) 保留字

为了向将来Javascript的新版本过渡,严格模式新增了一些保留字:implements, interface, let, package, private, protected, public, static, yield。

使用这些词作为变量名将会报错。

1
2
3
4
5
6
7
  function package(protected) { // 语法错误

    "use strict";

    var implements; // 语法错误

  }

此外,ECMAscript第五版本身还规定了另一些保留字(class, enum, export, extends, import, super),以及各大浏览器自行增加的const保留字,也是不能作为变量名的。

[3] 语句

(1)语句以一个分号结尾;如果省略分号,则由解释器确定语句的结尾(建议不要忽略)

[4] 关键字和保留字

es3 es5(*标识):

1
2
3
4
5
6
7
8
9
10
11
break	do instanceof typeof

case else new var

catch finally return void

debugger* function this with

default if throw

delete in try

ecma-262还描述了另外一组不能用标识符的保留字。尽管保留字。尽管保留字在这门

es3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
abstract	enum	int short

boolean export interface static

byte extentds long super

char final native synchronized

class float package throws

const goto private transient

debugger implement protected volatile

double import public

es5:

把非严格模式下运行时的保留字缩减为下列这些:

1
2
3
class	enum	extends	super

const export import
1
2
3
4
5
implement	package	public

interface private static

let protected yield

3.语句

(1)分号

Q1: 解释器如何判断是否需自动增加分号:

解释器会判断前后语句是否可以放一起执行,如果可以合并为一句,如果不可以就补全分号,再不行就报错。

特例有如下2个

[1] return breank contiune

不会合并,直接结束。(return后的部分请不要换行)

1
2
3
4
5
6
function a() {
var res = 'aaa';
return
res; // 不会返回aaa

}

[2] ++ –等操作符

不会与上行语句合并,而会与下语句合并

1
2
3
4
5
6
7
8
9
10
var a = 1;

var b = 2;

a
++
b

console.log(a);
console.log(b);

(2)括号

建议能使用则使用

补充(变量类型)

ECMAscript的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。换句话说,每个变量仅仅是用于保存值的占位符而已。 js在定义变量时,不会严格限制类型,而是使用(调用的时候)的时候分配类型

Share