6.JavaScript常用语法参考一览表

JavaScript是一种动态弱类型语言(dynamically typed language)。这意味着你在声明变量时可以不必指定数据类型,而数据类型会在代码执行时会根据需要自动转换。语句的话建议以 ; 结尾。

1.注释

// 单行注释

/* 这是一个更长的,
   多行注释
*/

2.标识符

标识符必须以字母、下划线(_)或者美元符号($)开头;后续的字符也可以是字母、下划线(_)、美元符号($)和数字(0-9)。因为 JavaScript 语言是区分大小写的,所以字母可以是从“A”到“Z”的大写字母和从“a”到“z”的小写字母。

3.语句块

{
   statement_1;   
   statement_2;
   statement_3;
   .
   .
   .
   statement_n;
}

示例:

while (x < 10) {
  x++;
}

这里{ x++; }就是语句块。

4.变量

变量可以保存任何类型的数据,分为不带关键字、带关键字var(函数作用域)和let(块作用域)三种类型。

如果只声明未初始化,则其值为 undefined

4.1不带关键字的变量(极不推荐)

不带关键字的变量当在函数内部声明或函数外部声明或代码块内声明都是全局变量,极不推荐

x = 8

4.2带var关键字的变量(怪异的作用域)

在函数之外声明的var变量,为 全局变量,因为它可被当前文档中的任何其他代码所访问。

在函数内部声明的var变量,为 局部变量,因为它只能在当前函数的内部访问。

var x = 8;      #声明局部变量或全局变量。

ECMAScript 6 之前的 JavaScript 没有 语句块 作用域,语句块中声明的变量的作用域即语句块所在函数(或全局作用域)的对应作用域。例如,如下的代码将在控制台输出 5,因为 x 的作用域是声明了 x 的那个函数(或全局范围)的作用域,而不是 if 语句块。

if (true) {
  var x = 5;
}
console.log(x); // 5

4.3带let关键字的变量(推荐)

在函数之外声明的let变量,为 全局变量;在函数内部声明的let变量,为 局部变量

如果使用 ECMAScript 6 中新增的 let 声明,上述行为将发生变化。let 声明的变量的范围是块作用域,而var声明的范围是函数作用域。

if (true) {
  let y = 5;
}
console.log(y); // ReferenceError: y 没有被声明

5.常量

可以用关键字 const 创建一个只读的常量。常量标识符的命名规则和变量相同:必须以字母、下划线(_)或美元符号($)开头并可以包含有字母、数字或下划线。

const PI = 3.14;

常量不可以通过重新赋值改变其值,也不可以在代码运行时重新声明。它必须声明时同时被初始化为某个值。

常量的作用域规则与 let 块级作用域变量相同。若省略const关键字,则该标识符将被视为变量。

在同一作用域中,不能使用与变量名或函数名相同的名字来命名常量。

6.数据类型(Type)和值(Value)

最新的 ECMAScript 标准定义了8种数据类型:

  • 七种原始值数据类型(primitive value):
    • Null(空)类型:只有一个叫做null的值,表示空值。null表示”没有对象”,即该处不应该有值。 JavaScript 是大小写敏感的,因此 null 与 NullNULL或变体完全不同。
    • Undefined(未定义)类型:和Null一样是一个特殊的类型,只有一个叫做undefined的值。表示声明了变量但未初始化。undefined表示”缺少值”,就是此处应该有一个值,但是还没有定义。
    • Boolean(布尔)类型:有2个值分别是:true 和 false
    • Number(数值)类型:整数或浮点数,例如: 42 或者 3.14159。精确到双精度64位宽18437736874454810627( 2的64次方 – 2的53次方+ 3 ),特殊值NaN(Not a Number)。
    • BigInt(任意精度的数值)类型:可以安全地存储和操作任意大整数,不受制于位宽,甚至可以超过数字的安全整数限制。
    • String(字符串)类型:字符串是一串表示文本值的字符序列,例如:”Howdy” 。
    • Symbol(符号)类型:值是唯一的且永远不能改变的,通常用作属性的键(the keys of properties),每个符号都与称作[[Description]]相关联,[[Description]]要么是undefined要么是String值
  • 引用值数据类型(reference value):对象(Object)。

数据类型的值分为原始值(primitive values)和引用值(reference value)。

7.条件判断

7.1if...else 语句

当一个逻辑条件为真,用if语句执行一个语句。当这个条件为假,使用可选择的 else 从句来执行这个语句。if 语句如下所示:

if (condition) {
  statement_1;
}else {
  statement_2;
}
if (condition_1) {
  statement_1;
}else if (condition_2) {
  statement_2;
}else if (condition_n_1) {
  statement_n;
}else {
  statement_last;
}

7.2switch 语句

switch 语句允许一个程序求一个表达式的值并且尝试去匹配表达式的值到一个 case 标签。如果匹配成功,这个程序执行相关的语句。switch 语句如下所示:

switch (expression) {
   case label_1:
      statements_1
      [break;]
   case label_2:
      statements_2
      [break;]
   ...
   default:
      statements_def
      [break;]
}

8.循环语句

8.1for 语句

一个 for 循环会一直重复执行,直到指定的循环条件为 false。

for ([initialExpression]; [condition]; [incrementExpression])
  statement

8.2do...while 语句

do...while 语句一直重复直到指定的条件求值得到假值(false)。 一个 do…while 语句看起来像这样:

do
  statement
while (condition);

8.3while 语句

一个 while 语句只要指定的条件求值为真(true)就会一直执行它的语句块。一个 while 语句看起来像这样:

while (condition)
  statement

8.4label 语句

一个 label 提供了一个让你在程序中其他位置引用它的标识符。例如,你可以用 label 标识一个循环, 然后使用 break 或者 continue 来指出程序是否该停止循环还是继续循环。

label 语句的语法看起来像这样:

label :
   statement

8.5break 语句

在语法中,被 [] 包裹的内容是可省略的,也就是 label 可以省略。若省略,则终止当前所在的循环或 switch;若不省略,则终止指定的 label 语句。

break [label];

8.6continue 语句

continue 语句可以用来继续执行(跳过代码块的剩余部分并进入下一循环)一个 whiledo-whilefor,或者 label 语句。

  • 当你使用不带 label 的 continue 时, 它终止当前 whiledo-while,或者 for 语句到结尾的这次的循环并且继续执行下一次循环。
  • 当你使用带 label 的 continue 时, 它会应用被 label 标识的循环语句。

continue 语句的语法看起来像这样:

continue [label];

8.7for...in 语句

for...in 语句循环一个指定的变量来循环一个对象所有可枚举的属性。

for (variable in object) {
  statements
}

8.8for...of 语句

for...of 语句在可迭代对象(包括ArrayMapSetarguments 等等)上创建了一个循环,对值的每一个独特属性调用一次迭代。

for (variable of object) {
  statement
}

9.运算符

  • 赋值运算符(Assignment operators)
  • 比较运算符(Comparison operators)
  • 算数运算符(Arithmetic operators)
  • 位运算符(Bitwise operators)
  • 逻辑运算符(Logical operators)
  • 字符串运算符(String operators)
  • 条件(三元)运算符(Conditional operator)
  • 逗号运算符(Comma operator)
  • 一元运算符(Unary operators)
  • 关系运算符(Relational operator)

详细讲解见:Javascript运算符参考一览表

10.引用类型和对象(Object)

引用类型 又称为 对象定义,也被称为 引用值 对象引用类型 的一个实例。引用类型 描述的是一类对象所具有的属性和方法。函数 也是一种 引用类型

Object 是派生其他对象的基类。

10.1创建实例

a.操作符new创建法

创建Object引用类型的实例,使用new操作符后跟 构造函数Object() 创建,接着把该实例保存在person变量中,然后再给对象添加属性和方法。

let person = new object();  
person.name = "张三";
person.age = 28;
person.sayName = function() {
  console.log(this.name);
};
b.对象字面量创建法(推荐)

我们定义(创建)了一个 JavaScript 对象:

let person = {
name : "张三",
age : 28,
sayName() {
  console.log(this.name);
}
};

10.2访问对象属性和方法

objectName.propertyName
objectName.methodName()

11.数组对象(Array)

数组(array)是一个有序的数据集合,数组中每个元素可以是任意数据类型,数组元素的长度会随着数据添加而自动增长,我们可以通过数组名称(name)和索引(index)进行访问。

11.1创建数组

let arr = new Array(element0, element1, ..., elementN);     #操作符new创建法
let arr = Array(element0, element1, ..., elementN);         #操作符new创建法的简写
let arr = [element0, element1, ..., elementN];              #对象字面量创建法(推荐)

// let arr=[4] 和 let arr=new Array(4)是不等效的,
// 后者4指数组长度,所以使用字面值(literal)的方式应该不仅仅是便捷,同时也不易踩坑

11.2遍历数组(interating over array)

遍历数组元素并以某种方式处理每个元素是一个常见的操作。以下是最简单的方式:

let colors = ['red', 'green', 'blue'];
for (let i = 0; i < colors.length; i++) {
  console.log(colors[i]);
}

11.3多维数组(multi-dimensional arrays)

数组是可以嵌套的, 这就意味着一个数组可以作为一个元素被包含在另外一个数组里面。利用JavaScript数组的这个特性, 可以创建多维数组。

以下代码创建了一个二维数组。

let a = new Array(4);
for (i = 0; i < 4; i++) {
  a[i] = new Array(4);
  for (j = 0; j < 4; j++) {
    a[i][j] = "[" + i + "," + j + "]";
  }
}

这个例子创建的数组拥有以下行数据:

Row 0: [0,0] [0,1] [0,2] [0,3]
Row 1: [1,0] [1,1] [1,2] [1,3]
Row 2: [2,0] [2,1] [2,2] [2,3]
Row 3: [3,0] [3,1] [3,2] [3,3]

12.函数(Function)

12.1构造器定义函数法

Function 也是一种 引用类型。每个 JavaScript 函数实际上都是一个 Function 对象。运行 (function(){}).constructor === Function // true 便可以得到这个结论。

语法:

new Function ([arg1[, arg2[, ...argN]],] functionBody)

arg1, arg2, ... argN被函数使用的参数的名称必须是合法命名的。参数名称是一个有效的JavaScript标识符的字符串,或者一个用逗号分隔的有效字符串的列表;例如“×”,“theValue”,或“a,b”。functionBody一个含有包括函数定义的 JavaScript 语句的字符串

示例:

const sum = new Function('a', 'b', 'return a + b');

console.log(sum(2, 6));
// expected output: 8

12.2表达式定义函数法

let function_expression = function [name]([param1[, param2[, ..., paramN]]]) {
   statements
};

name函数名称,可被省略,此种情况下的函数是匿名函数(anonymous)。 函数名称只是函数体中的一个本地变量。paramN被传递给函数的一个参数名称,一个函数至多拥有 255 个参数。statements构成函数体的语句。

函数表达式(function expression)非常类似于函数声明(function statement),并且两者拥有几乎相同的语法。函数表达式与函数声明的最主要区别是函数名称(function name),在函数表达式中可省略它,从而创建匿名函数(anonymous functions)。

12.3声明定义函数法

函数声明定义一个具有指定参数的函数。

function name([param,[, param,[..., param]]]) {
   [statements]
}

name函数名param要传递给函数的参数的名称。不同引擎中的最大参数数量不同。statements包含函数体的语句。

12.4箭头函数表达式(arrow function)

箭头函数表达式的语法比函数表达式更简洁,并且没有自己的thisargumentssupernew.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。

基础语法

(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
//相当于:(param1, param2, …, paramN) =>{ return expression; }

// 当只有一个参数时,圆括号是可选的:
(singleParam) => { statements }
singleParam => { statements }

// 没有参数的函数应该写成一对圆括号。
() => { statements }

高级语法

//加括号的函数体返回对象字面量表达式:
params => ({foo: bar})

//支持剩余参数和默认参数
(param1, param2, ...rest) => { statements }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => {
statements }

//同样支持参数列表解构
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f();  // 6
let elements = [
  'Hydrogen',
  'Helium',
  'Lithium',
  'Beryllium'
];

elements.map(function(element) {
  return element.length;
}); // 返回数组:[8, 6, 7, 9]

// 上面的普通函数可以改写成如下的箭头函数
elements.map((element) => {
  return element.length;
}); // [8, 6, 7, 9]

// 当箭头函数只有一个参数时,可以省略参数的圆括号
elements.map(element => {
 return element.length;
}); // [8, 6, 7, 9]

// 当箭头函数的函数体只有一个 `return` 语句时,可以省略 `return` 关键字和方法体的花括号
elements.map(element => element.length); // [8, 6, 7, 9]

// 在这个例子中,因为我们只需要 `length` 属性,所以可以使用参数解构
// 需要注意的是字符串 `"length"` 是我们想要获得的属性的名称,而 `lengthFooBArX` 则只是个变量名,
// 可以替换成任意合法的变量名
elements.map(({ "length": lengthFooBArX }) => lengthFooBArX); // [8, 6, 7, 9]

12.5嵌套函数和闭包

你可以在一个函数里面嵌套另外一个函数。嵌套(内部)函数对其容器(外部)函数是私有的。它自身也形成了一个闭包。一个闭包是一个可以自己拥有独立的环境与变量的表达式(通常是函数)。

既然嵌套函数是一个闭包,就意味着一个嵌套函数可以”继承“容器函数的参数和变量。换句话说,内部函数包含外部函数的作用域。

可以总结如下:

  • 内部函数只可以在外部函数中访问。
  • 内部函数形成了一个闭包:它可以访问外部函数的参数和变量,但是外部函数却不能使用它的参数和变量。

下面的例子展示了嵌套函数:

function addSquares(a, b) {
  function square(x) {
    return x * x;
  }
  return square(a) + square(b);
}
a = addSquares(2, 3); // returns 13
b = addSquares(3, 4); // returns 25
c = addSquares(4, 5); // returns 41

由于内部函数形成了闭包,因此你可以调用外部函数并为外部函数和内部函数指定参数:

function outside(x) {
  function inside(y) {
    return x + y;
  }
  return inside;
}
fn_inside = outside(3); // 可以这样想:给一个函数,使它的值加3
result = fn_inside(5); // returns 8

result1 = outside(3)(5); // returns 8

12.6闭包

闭包是 JavaScript 中最强大的特性之一。JavaScript 允许函数嵌套,并且内部函数可以访问定义在外部函数中的所有变量和函数,以及外部函数能访问的所有变量和函数。

但是,外部函数却不能够访问定义在内部函数中的变量和函数。这给内部函数的变量提供了一定的安全性。

此外,由于内部函数可以访问外部函数的作用域,因此当内部函数生存周期大于外部函数时,外部函数中定义的变量和函数的生存周期将比内部函数执行时间长。当内部函数以某一种方式被任何一个外部函数作用域访问时,一个闭包就产生了。

let pet = function(name) {          //外部函数定义了一个变量"name"
  let getName = function() {            
    //内部函数可以访问 外部函数定义的"name"
    return name; 
  }
  //返回这个内部函数,从而将其暴露在外部函数作用域
  return getName;               
};
myPet = pet("Vivie");
    
myPet();                  

关于闭包详见:Javascript中的闭包的讲解

13.类(Class)

类是用于创建对象的模板。他们用代码封装数据以处理该数据。实际上,类是“特殊的函数”,就像你能够定义的函数表达式和函数声明一样,定义类的方法有两种:类表达式和类声明。

13.1类声明

定义类的一种方法是使用类声明。要声明一个类,你可以使用带有class关键字的类名。

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

13.2类表达式

类表达式是定义类的另一种方法。类表达式可以命名或不命名。命名类表达式的名称是该类体的局部名称。(不过,可以通过类的(而不是一个实例的) name 属性来检索它)。

// 未命名/匿名类
let Rectangle = class {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};
console.log(Rectangle.name);
// output: "Rectangle"

// 命名类
let Rectangle = class Rectangle2 {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};
console.log(Rectangle.name);
// 输出: "Rectangle2"

13.3类的继承

extends关键字用于类声明或者类表达式中,以创建一个类,该类是另一个类的子类。

语法:

class ChildClass extends ParentClass { ... }

extends关键字用来创建一个普通类或者内建对象的子类。

继承的.prototype必须是一个Object 或者 null

示例:

class Square extends Polygon {
  constructor(length) {
    // Here, it calls the parent class' constructor with lengths
    // provided for the Polygon's width and height
    super(length, length);
    // Note: In derived classes, super() must be called before you
    // can use 'this'. Leaving this out will cause a reference error.
    this.name = 'Square';
  }

  get area() {
    return this.height * this.width;
  }
}

13.4类方法

类(class)通过 static 关键字定义静态方法。不能在类的实例上调用静态方法,而应该通过类本身调用。这些通常是实用程序方法,例如创建或克隆对象的功能。

class ClassWithStaticMethod {

  static staticProperty = 'someValue';
  static staticMethod() {
    return 'static method has been called.';
  }

}

console.log(ClassWithStaticMethod.staticProperty);
// output: "someValue"
console.log(ClassWithStaticMethod.staticMethod());
// output: "static method has been called."

13.5super

super关键字用于访问和调用一个对象的父对象上的函数。

super([arguments]);
// 调用 父对象/父类 的构造函数

super.functionOnParent([arguments]);
// 调用 父对象/父类 上的方法
class Polygon {
  constructor(height, width) {
    this.name = 'Rectangle';
    this.height = height;
    this.width = width;
  }
  sayName() {
    console.log('Hi, I am a ', this.name + '.');
  }
  get area() {
    return this.height * this.width;
  }
  set area(value) {
    this._area = value;
  }
}

class Square extends Polygon {
  constructor(length) {
    this.height; // ReferenceError,super 需要先被调用!

    // 这里,它调用父类的构造函数的,
    // 作为Polygon 的 height, width
    super(length, length);

    // 注意: 在派生的类中, 在你可以使用'this'之前, 必须先调用super()。
    // 忽略这, 这将导致引用错误。
    this.name = 'Square';
  }
}
class Rectangle {
  constructor() {}
  static logNbSides() {
    return 'I have 4 sides';
  }
}

class Square extends Rectangle {
  constructor() {}
  static logDescription() {
    return super.logNbSides() + ' which are all equal';
  }
}
Square.logDescription(); // 'I have 4 sides which are all equal'

原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/basic/js/1939.html

发表评论

邮箱地址不会被公开。 必填项已用*标注