TypeError: setting getter-only property "x" - JavaScript

TypeError: setting getter-only property "x"
===========================================

错误提示
----
```

TypeError: setting getter-only property "x" (Firefox)
TypeError: Cannot set property "prop" of #<Object> which has only a getter (Chrome)
```

错误类型
----

仅在严格模式下报 `TypeError` 错误。

哪里出错了？
------

该错误提示出现于试图给一个仅仅设置了 getter 特性的属性赋新值的时候。在非严格模式下会被静默忽略，而在严格模式下会报 `TypeError` 错误。

示例
--

下面的例子展示了如何为一个属性设置 getter 特性。由于没有设置 setter 特性，所以在试图将 temperature 属性值设置为 30 的时候会报 TypeError 的错误。相关细节信息可以参考 `Object.defineProperty()` 页面。

```js
"use strict";

function Archiver() {
  var temperature = null;
  Object.defineProperty(this, "temperature", {
    get: function () {
      console.log("get!");
      return temperature;
    },
  });
}

var arc = new Archiver();
arc.temperature; // 'get!'

arc.temperature = 30;
// TypeError: setting getter-only property "temperature"
```

至于修复问题的方法，可以将第 16 行的代码移除，因为它试图为 temperature 属性赋值，或者是为它添加一个 setter 特性，就像下面这样：

```js
"use strict";

function Archiver() {
  var temperature = null;
  var archive = [];

  Object.defineProperty(this, "temperature", {
    get: function () {
      console.log("get!");
      return temperature;
    },
    set: function (value) {
      temperature = value;
      archive.push({ val: temperature });
    },
  });

  this.getArchive = function () {
    return archive;
  };
}

var arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;
arc.temperature = 13;
arc.getArchive(); // [{ val: 11 }, { val: 13 }]
```

相关内容
----

* `Object.defineProperty()`
* `Object.defineProperties()`


SyntaxError: missing ] after element list - JavaScript

SyntaxError: missing ] after element list
=========================================

信息
--
```

SyntaxError: missing ] after element list
```

错误类型
----

`SyntaxError`.

哪里出错了？
------

数组初始化在某处出现了语法错误。比如缺少了右中括号 ("`]`") 或一个逗号 ("`,`")。

示例
--

### 不正确的数组初始化

```js
var list = [1, 2,

var instruments = [
  "Ukulele",
  "Guitar",
  "Piano"
};

var data = [{foo: "bar"} {bar: "foo"}];
```

正确的是：

```js
var list = [1, 2];

var instruments = ["Ukulele", "Guitar", "Piano"];

var data = [{ foo: "bar" }, { bar: "foo" }];
```

相关
--

* `Array`


SyntaxError: missing : after property id - JavaScript

SyntaxError: missing : after property id
========================================

错误提示
----
```

SyntaxError: missing : after property id
```

错误类型
----

`SyntaxError`哪里出错了？
------

当使用对象初始化语法创建对象的时候，需要使用半角冒号 (:) 将属性键与属性值隔开。

```js
var obj = { propertyKey: "value" };
```

示例
--

### 冒号与等号

下面的代码会运行失败，原因是对象初始化语法中不允许使用等号来代替冒号。

```js
var obj = { propertyKey = 'value' };
// SyntaxError: missing : after property id
```

修复方法就是使用冒号，或者是在对象创建之后使用方括号语法来为其设定新的属性。

```js
var obj = { propertyKey: "value" };

// or alternatively

var obj = {};
obj["propertyKey"] = "value";
```

### 空属性

不能像下面这样创建空属性：

```js
var obj = { propertyKey; };
// SyntaxError: missing : after property id
```

假如你需要创建一个无值属性，那么需要将它的值设置为 `null` 。

```js
var obj = { propertyKey: null };
```

### 计算得来的属性

如果需要使用表达式来创建属性键，那么需要使用方括号。否则属性名称不会进行计算：

```js
var obj = { 'b'+'ar': 'foo' };
// SyntaxError: missing : after property id
```

把计算表达式放置到方括号（`[]`）中：

```js
var obj = { ["b" + "ar"]: "foo" };
```

相关内容
----

* Object initializer


URIError: malformed URI sequence - JavaScript

URIError: malformed URI sequence
================================

错误提示
----
```

URIError: malformed URI sequence (Firefox)
URIError: URI malformed (Chrome)
```

错误类型
----

`URIError`哪里出错了？
------

URI 编码和解码不成功。传递给 `decodeURI`、`encodeURI`、`encodeURIComponent` 或者 `decodeURIComponent` 这些函数的参数不合法，导致函数无法正确对其进行编解码。

示例
--

### 编码

编码操作会将每一个字符实例替换为一到四个相对应的 UTF-8 编码形式的转义序列。如果试图编码一个非高 - 低位完整的代理字符，将会抛出一个 `URIError` 错误，例如：

```js
encodeURI("\uD800");
// "URIError: malformed URI sequence"

encodeURI("\uDFFF");
// "URIError: malformed URI sequence"
```

高 - 低位完整的代理字符是没问题的，例如：

```js
encodeURI("\uD800\uDFFF");
// "%F0%90%8F%BF"
```

### 解码

解码操作则是将已经经过编码的 URL 片段中的每一个转义序列替换为相对应的字符。如果相应的字符不存在，就会抛出错误：

```js
decodeURIComponent("%E0%A4%A");
// "URIError: malformed URI sequence"
```

输入没问题的话，通常是下面这样：

```js
decodeURIComponent("JavaScript\_%D1%88%D0%B5%D0%BB%D0%BB%D1%8B");
// "JavaScript\_шеллы"
```

相关内容
----

* `URIError`
* `decodeURI`
* `encodeURI`
* `encodeURIComponent`
* `decodeURIComponent`


SyntaxError: missing } after function body - JavaScript

SyntaxError: missing } after function body
==========================================

错误提示
----
```

SyntaxError: missing } after function body
```

错误类型
----

`SyntaxError`哪里出错了？
------

在创建函数的时候出现了语法错误。检查一下闭合花括号以及括号的顺序是否正确。将代码进行缩进或者美化可以让你更容易找到问题之所在。

示例
--

### 遗漏的闭合花括号

通常是因为在函数声明中遗漏了花括号：

```js
var charge = function() {
  if (sunny) {
    useSolarCells();
  } else {
    promptBikeRide();
};
```

正确的应该是这样的：

```js
var charge = function () {
  if (sunny) {
    useSolarCells();
  } else {
    promptBikeRide();
  }
};
```

当使用立即调用函数表达式（IIFE）、闭包或者其他使用了大量的花括号以及括号的结构体的时候，问题会更加隐蔽。

```js
(function() { if (true) { return false; } );
```

通常将代码语句按照层级缩进以及对缩进进行复核会有助于错误的发现。

```js
(function () {
  if (true) {
    return false;
  }
});
```

相关内容
----

* Functions


SyntaxError: identifier starts immediately after numeric literal - JavaScript

SyntaxError: identifier starts immediately after numeric literal
================================================================

Message
-------
```

SyntaxError: identifier starts immediately after numeric literal (Firefox)
SyntaxError: Unexpected number (Chrome)
```

Error type
----------

`SyntaxError`What went wrong?
----------------

变量名叫identifiers，它符合某些规则，而你打破了这些规则！

一个 JavaScript 标识符必须以字母开头，下划线（\_）或美元符号（$）。他们不能以数字开头。只有后续字符可以是数字（0-9）。

Examples
--------

### Variable names starting with numeric literals

Variable names can't start with numbers in JavaScript. The following fails:

```js
var 1life = 'foo';
// SyntaxError: identifier starts immediately after numeric literal

var foo = 1life;
// SyntaxError: identifier starts immediately after numeric literal
```

You will need to rename your variable to avoid the leading number.

```js
var life1 = "foo";
var foo = life1;
```

See also
--------

* Lexical grammar
* Variables in the JavaScript Guide


TypeError: "x" is read-only - JavaScript

TypeError: "x" is read-only
===========================

报错消息
----
```

TypeError: "x" is read-only (Firefox) //格式错误："x"只读。(x 可以代表任意值)
TypeError: 0 is read-only (Firefox)
TypeError: Cannot assign to read only property 'x' of #<Object> (Chrome)
//格式错误：对象的 x 属性是只读的不能设置（chrome）
TypeError: Cannot assign to read only property '0' of [object Array] (Chrome)
```

错误格式
----

`TypeError`哪里出错了？
------

全局变量或对象属性被设置为只读 (专业点讲，就是这条数据属性禁止写入.)

这条错误值发生在strict mode code(俗称严格模式). 正常情况下，是没有报错的。

例如
--

### 无效例子（也就是下面这么做会导致报这种错）

只读属性不能直接创建，但我们可以通过`Object.defineProperty()` 或 `Object.freeze()`设置。

```js
"use strict";
var obj = Object.freeze({name: "Elsa", score: 157});
obj.score = 0;  // TypeError

"use strict";
Object.defineProperty(this, "LUNG\_COUNT", {value: 2, writable: false});
LUNG\_COUNT = 3;  // TypeError

"use strict";
var frozenArray = Object.freeze([0, 1, 2]);
frozenArray[0]++;  // TypeError

还有几个 JavaScript 内置属性。如果你尝试修改一个常量。

"use strict";
Math.PI = 4;  // TypeError
```

傻了吧，报错了

`全局变量 undefined 也是只读的`, 所以你不能忽视臭名昭著的"undefined is not a function"错误：

```js
"use strict";
undefined = function () {}; // TypeError: "undefined" is read-only
```

### 下面这样都是有效，不报错的

```js
"use strict";
var obj = Object.freeze({ name: "Score", points: 157 });
obj = { name: obj.name, points: 0 }; // 用一个新对象替换原来的对象 (其实就是更改了对象的指针)

("use strict");
var LUNG\_COUNT = 2; //
LUNG\_COUNT = 3; //
```

参见
--

* `Object.defineProperty()`
* `Object.freeze()`
* "Which animals have three lungs?" on answers.com
* Klingons (another answer to that query)


RangeError: precision is out of range - JavaScript

RangeError: precision is out of range
=====================================

描述
--
```

RangeError: precision {0} out of range (Firefox)
RangeError: toExponential() argument must be between 0 and 20 (Chrome)
RangeError: toFixed() digits argument must be between 0 and 20 (Chrome)
RangeError: toPrecision() argument must be between 1 and 21 (Chrome)
```

错误类型
----

`RangeError`什么地方出错了？
--------

以下的某个方法传入了一个超出精度范围的参数：

* `Number.prototype.toExponential()`
* `Number.prototype.toFixed()`
* `Number.prototype.toPrecision()`

通常这些方法允许的参数范围介于 0 和 20（或 21）之间。需要注意的是，ECMAScript 标准是允许扩展这个范围的。

| Method | Firefox (SpiderMonkey) | Chrome, Opera (V8) |
| --- | --- | --- |
| `Number.prototype.toExponential()` | 0 to 100 | 0 to 20 |
| `Number.prototype.toFixed()` | -20 to 100 | 0 to 20 |
| `Number.prototype.toPrecision()` | 1 to 100 | 1 to 21 |

示例
--

### 错误的示例

```js
(77.1234).toExponential(-1); // RangeError
(77.1234).toExponential(101); // RangeError

(2.34).toFixed(-100); // RangeError
(2.34).toFixed(1001); // RangeError

(1234.5).toPrecision(-1); // RangeError
(1234.5).toPrecision(101); // RangeError
```

### 正确的示例

```js
(77.1234).toExponential(4); // 7.7123e+1
(77.1234).toExponential(2); // 7.71e+1

(2.34).toFixed(1); // 2.3
(2.35).toFixed(1); // 2.4 (note that it rounds up in this case)

(5.123456).toPrecision(5); // 5.1235
(5.123456).toPrecision(2); // 5.1
(5.123456).toPrecision(1); // 5
```

相关页面
----

* `Number.prototype.toExponential()`
* `Number.prototype.toFixed()`
* `Number.prototype.toPrecision()`


TypeError: invalid assignment to const "x" - JavaScript

TypeError: invalid assignment to const "x"
==========================================

错误提示
----
```

TypeError: invalid assignment to const "x" (Firefox)
TypeError: Assignment to constant variable. (Chrome)
TypeError: Redeclaration of const 'x' (IE/Edge)
```

错误类型
----

`TypeError`哪里出错了？
------

常量指的是无法在程序正常运行过程中进行修改的值。一方面无法通过重新赋值进行修改，另外一方面也无法进行重新声明。在 JavaScript 中，常量通过关键字 `const` 来声明。

示例
--

### 不合法的二次声明

在同一作用域内为相同的常量名进行赋值会报错。

```js
const COLUMNS = 80;

// ...

COLUMNS = 120; // TypeError: invalid assignment to const `COLUMNS'
```

### 问题修复

修复的方式有很多种。可以根据你想要达到的目的来有针对性地对其进行处理。

#### 重新命名

如果想要声明另一个变量，那么请选择其他名称对其重新命名。原来的常量名在该作用域中已经被占有。

```js
const COLUMNS = 80;
const WIDE\_COLUMNS = 120;
```

#### `const`, `let` or `var`?

如果你的目的不是为了创建一个常量的话，那么就不要使用 const 关键字。可以使用 `let` 关键字来声明一个拥有块作用域的变量，或者使用 `var` 来声明一个全局变量。

```js
let columns = 80;

// ...

let columns = 120;
```

#### 作用域

检查一下作用域是否正确。例如这个常量是否应该出现在当前作用域，还是应该出现在函数内部？

```js
const COLUMNS = 80;

function setupBigScreenEnvironment() {
  const COLUMNS = 120;
}
```

### `const 与不可变性`

const 声明语句创建了一个对值的只读引用。这并**不**意味着它指向的值是不可变的，而是说这个变量标记符不能被再次分配。例如，在值是对象的情况下，引用的对象自身内容依然是可以改变的。不能改变该变量的引用：

```js
const obj = { foo: "bar" };
obj = { foo: "baz" }; // TypeError: invalid assignment to const `obj'
```

但是可以改变它引用的值的属性：

```js
obj.foo = "baz";
obj; // Object { foo: "baz" }
```

相关内容
----

* `const`
* `let`
* `var`


TypeError: 'x' is not iterable - JavaScript

TypeError: 'x' is not iterable
==============================

错误信息
----
```

TypeError: 'x' is not iterable (Firefox, Chrome)
TypeError: 'x' is not a function or its return value is not iterable (Chrome)
```

错误类型
----

`TypeError`发生了什么错误？
--------

这个值作为 for…of 的表达式右值，或者作为一个函数的参数，如 `Promise.all` 或者 `TypedArray.from`, 不是一个 可迭代对象. 一个可迭代对象可以是一个内置可迭代类型，如`Array`, `String` 或 `Map`, 一个 generator 生成结果，或者一个实现了 可迭代协议 的对象

示例
--

### Iterating over Object properties

在 JavaScript 中，`Object` 是不可迭代的，除非它们实现了迭代协议. 因此，你不能使用 for…of 来迭代对象的属性。

```js
var obj = { France: "Paris", England: "London" };
for (let p of obj) {
  // TypeError: obj is not iterable
  // …
}
```

做为替代你必须使用 `Object.keys` 或 `Object.entries` 来迭代对象的属性或属性值。

```js
var obj = { France: "Paris", England: "London" };
// 迭代属性名称：
for (let country of Object.keys(obj)) {
  var capital = obj[country];
  console.log(country, capital);
}

for (const [country, capital] of Object.entries(obj))
  console.log(country, capital);
```

这次 case 的另外一个选择是使用 `Map`:

```js
var map = new Map();
map.set("France", "Paris");
map.set("England", "London");
// Iterate over the property names:
for (let country of map.keys()) {
  let capital = map[country];
  console.log(country, capital);
}

for (let capital of map.values()) console.log(capital);

for (const [country, capital] of map.entries()) console.log(country, capital);
```

### Iterating over a generator

生成器是用来生成可迭代对象的函数。

```js
function\* generate(a, b) {
  yield a;
  yield b;
}

for (let x of generate) // TypeError: generate is not iterable
  console.log(x);
```

当它没有被调用，这个 `Function` 相应的是可调用的，但是不可迭代。调用 generator 生成一个可迭代对象，该对象将迭代在生成器执行期间生成的值。

```js
function\* generate(a, b) {
  yield a;
  yield b;
}

for (let x of generate(1, 2)) console.log(x);
```

### Iterating over a custom iterable

可以使用`Symbol.iterator` 方法去实现一个自定义迭代器。你必须确定自定义的迭代器方法返回一个迭代器对象，即它必须有一个 next()

```js
const myEmptyIterable = {
  [Symbol.iterator]() {
    return []; // [] is iterable, but it is not an iterator -- it has no next method.
  },
};

Array.from(myEmptyIterable); // TypeError: myEmptyIterable is not iterable
```

下面是正确用法

```js
const myEmptyIterable = {
  [Symbol.iterator]() {
    return [][Symbol.iterator]();
  },
};

Array.from(myEmptyIterable); // []
```

参阅
--

* iterable protocol
* `Object.keys`
* `Object.entries`
* `Map`
* 生成器
* for…of


ReferenceError: can't access lexical declaration`X' before initialization - JavaScript

ReferenceError: can't access lexical declaration`X' before initialization
=========================================================================

消息提示
----
```

ReferenceError: assignment to undeclared variable "x" (Firefox)
```

错误类型
----

`ReferenceError`哪里出错了？
------

词法变量在初始化之前被访问。该错误可以发生于任何语句块中，当使用 let 或 const 修饰的变量在初始化之前被访问的时候。

示例
--

### 非法情况

在这个例子中，变量 "foo" 在语句块中再次声明，导致未初始化。

```js
function test() {
  let foo = 33;
  if (true) {
    let foo = foo + 55; // ReferenceError: can't access lexical declaration `foo' before initialization
  }
}
test();
```

### 正确情况

在 if 语句块中修改变量 "foo" 的值，不应该在其中进行二次声明。

```js
function test() {
  let foo = 33;
  if (true) {
    foo = foo + 55;
  }
}
test();
```

相关内容
----

* let 的暂存死区及相关错误


SyntaxError: missing } after property list - JavaScript

SyntaxError: missing } after property list
==========================================

信息
--
```

SyntaxError: missing } after property list
```

错误类型
----

`SyntaxError`哪里出错了？
------

在对象初始化的时候语法出错了。可能是遗漏了一个大括号，也可能是遗漏了逗号。还要检查是否以正确的顺序关闭了大括号或括号。缩进或格式化代码也许可以更好帮助你看清这些芜杂的。

示例
--

### 遗漏的逗号

很多情况下，对象初始值代码会中缺少逗号：

```js
var obj = {
  a: 1,
  b: { myProp: 2 }
  c: 3
};
```

正确的是：

```js
var obj = {
  a: 1,
  b: { myProp: 2 },
  c: 3,
};
```

相关
--

* Object initializer


SyntaxError: invalid regular expression flag "x" - JavaScript

SyntaxError: invalid regular expression flag "x"
================================================

信息
--
```

SyntaxError: invalid regular expression flag "x" (Firefox)
SyntaxError: Invalid regular expression flags (Chrome)
```

错误类型
----

`语法错误`.

什么地方出错了？
--------

在代码中出现了无效的正则表达式的标记。在一个正则表达式字面量中，由闭合的两条斜线组成一个模式，（正则表达式的）标记定义在第二个（斜线）标记之后。他们也可以通过`正则表达式` 对象的构造函数（第二个参数）来定义。正则表达式的标记可以单独或者任意次序的组合使用，但 ECMAScript 只规定了五个。

要使正则表达式包含标记，使用此语法：

```js
var re = /pattern/flags;
```

或

```js
var re = new RegExp("pattern", "flags");
```

| 标记 | 说明 |
| --- | --- |
| `g` | 整体检索。 |
| i | 忽略大小写检索。 |
| m | 多行检索。 |
| u | Unicode; 将模式视为 Unicode 码点的序列 |
| y | sticky 检索将从目标字符串的当前位置开始匹配。参阅`sticky` |

示例
--

只有 5 个有效的正则表达式标记。

```js
/foo/bar;

// SyntaxError: invalid regular expression flag "b"
```

你打算创建一个正则表达式吗？一个包含两条斜线的表达式被解释为一个正则表达式的字面量。

```js
let obj = {
  url: /docs/Web
};

// SyntaxError: invalid regular expression flag "W"
```

还是你想创建一个字符串呢？添加单引号或双引号创建一个字符串字面量。

```js
let obj = {
  url: "/docs/Web",
};
```

### 有效的正则表达式标记

在 JavaScript 中允许的五个有效的正则表达式标记，参阅上表。

```js
/foo/g;
/foo/gim;
/foo/uy;
```

相关页面
----

* 正则表达式
* XRegEx flags – 正则表达式库提供新的四个标记 (`n`, `s`, `x`, `A`)


SyntaxError: function statement requires a name - JavaScript

SyntaxError: function statement requires a name
===============================================

错误提示
----
```

SyntaxError: function statement requires a name [Firefox]
SyntaxError: Unexpected token ( [Chrome]
```

错误类型
----

`SyntaxError`哪里出错了？
------

函数声明需要提供函数名称。你需要检查函数是如何定义的，是否需要为其提供名称，出现问题的函数是否需要声明为函数表达式或立即调用函数表达式（IIFE），以及函数在上下文环境中出现的位置是否正确。

示例
--

### 语句与表达式

函数语句（或函数声明）需要命名，以下写法是不正确的：

```js
function () {
  return 'Hello world';
}
// SyntaxError: function statement requires a name
```

你可以使用函数表达式（赋值）来代替：

```js
var greet = function () {
  return "Hello world";
};
```

者是你想将其作为立即调用函数表达式（IIFE，Immediately Invoked Function Expression），也就是定义后立即执行的函数。在这种情况下你需要用到更多的括号：

```js
(function () {})();
```

### 标号函数 (Labeled functions)

你使用函数标号 (labels)的时候，也需要在关键词 `function` 后面提供一个函数名称。这样的代码是不能运行的：

```js
function Greeter() {
  german: function () {
    return "Moin";
  }
}
// SyntaxError: function statement requires a name
```

这个例子可以正常运行：

```js
function Greeter() {
  german: function g() {
    return "Moin";
  }
}
```

### 对象方法

如果你想创建创建一个对象方法，那么需要首先创建一个对象。以下语法（function 关键字后面没有提供名称）是合法的：

```js
var greeter = {
  german: function () {
    return "Moin";
  },
};
```

### 回调函数的语法

另外，如果使用到了回调函数，那么检查一下语法是否正确。大括号与逗号很容易使情况变糟。

```js
promise.then(
  function() {
    console.log("success");
  });
  function() {
    console.log("error");
}
// SyntaxError: function statement requires a name
```

正确的形式应该是这样的：

```json
promise.then(
  function() {
    console.log("success");
  },
  function() {
    console.log("error");
  }
);
```

相关内容
----

* Functions in the JavaScript Guide
* function statement
* function expression
* IIFE
* label


SyntaxError: missing formal parameter - JavaScript

SyntaxError: missing formal parameter
=====================================

信息提示
----
```

SyntaxError: missing formal parameter (Firefox)
```

错误类型
----

`SyntaxError`哪里出错了？
------

“形式参数”是“函数参数”一种更好的说法。函数声明缺少合法的参数定义。在函数声明中，参数定义必须为标记符（identifiers），而不是任何类似于数字、字符串或者对象的值。函数声明和函数调用是两个不同的步骤。函数声明中的参数需要使用标记符，而仅仅在函数被呼叫（调用）的时候才可以传入其所需要的值。

在 JavaScript 中，标记符只能由字母、数字、"$" 以及 "\_" 构成，并且不能以数字开头。标记符与**字符串**的区别在于字符串是数据，而标记符属于代码的一部分。

示例
--

在构造一个函数的时候，函数参数必须为标记符。下面列举的函数声明都是无效的，因为它们在参数部分使用的是数值：

```js
function square(3) {
  return number \* number;
};
// SyntaxError: missing formal parameter

function greet("Howdy") {
  return greeting;
};
// SyntaxError: missing formal parameter

function log({ obj: "value"}) {
  console.log(arg)
};
// SyntaxError: missing formal parameter
```

需要在函数声明中使用标记符：

```js
function square(number) {
  return number \* number;
}

function greet(greeting) {
  return greeting;
}

function log(arg) {
  console.log(arg);
}
```

之后可以传入你想要传入的实际参数调用函数：

```js
square(2); // 4

greet("Howdy"); // "Howdy"

log({ obj: "value" }); // Object { obj: "value" }
```

参见
--

* SyntaxError: redeclaration of formal parameter "x"


RangeError: repeat count must be non-negative - JavaScript

RangeError: repeat count must be non-negative
=============================================

信息
--
```

RangeError: repeat count must be non-negative (Firefox)
RangeError: Invalid count value (Chrome)
```

错误类型
----

`RangeError`发生了什么？
------

代码中使用了 `String.prototype.repeat()`方法。它有一个计数参数，表示重复该字符串的次数。该参数必须在 0 及正 `Infinity` 之间，且不能为负数。该值的合法范围可以这样表示： [0, +∞)。

示例
--

### 无效的

```js
"abc".repeat(-1); // RangeError
```

### 有效的

```js
"abc".repeat(0); // ''
"abc".repeat(1); // 'abc'
"abc".repeat(2); // 'abcabc'
"abc".repeat(3.5); // 'abcabcabc' (count will be converted to integer)
```

See also
--------

* `String.prototype.repeat()`


Error: Permission denied to access property "x" - JavaScript

Error: Permission denied to access property "x"
===============================================

消息
--
```

Error: Permission denied to access property "x"
```

错误类型
----

`错误`.

什么地方出错了？
--------

尝试访问无权访问的对象。这很可能出现在使用`<iframe>`元素时加载了一个不同域名下的页面，这在访问子页面时会违背同源策略。

示例
--

```html
<!doctype html>
<html>
  <head>
    <iframe
 id="myframe"
 src="http://www1.w3c-test.org/common/blank.html"></iframe>
    <script>
 console.log(document.getElementById("myframe").contentWindow.document);
 // Error: Permission denied to access property "document"
 </script>
  </head>
  <body></body>
</html>
```

可以参考

* `<iframe>`
* 同源策略


SyntaxError: for-in loop head declarations may not have initializers - JavaScript

SyntaxError: for-in loop head declarations may not have initializers
====================================================================

错误提示
----
```

SyntaxError: for-in loop head declarations may not have initializers (Firefox)

SyntaxError: for-in loop variable declaration may not have an initializer. (Chrome)
```

错误类型
----

该 `SyntaxError` 只出现于严格模式下。

哪里出错了？
------

在 for...in 循环的头部存在初始化表达式。也就是存在变量声明并且被赋值，例如 |`for (var i = 0 in obj)`|。在非严格模式下，这种在循环头部的变量声明会被静默忽略，语句的表现形式与 `|for (var i in obj)|`相同。而在严格模式下，会报语法错误。

示例
--

下面这个示例会报语法错误（`SyntaxError`）：

```js
"use strict";

var obj = {a: 1, b: 2, c: 3 };

for (var i = 0 in obj) {
  console.log(obj[i]);
}

// SyntaxError: for-in loop head declarations may not have initializers
```

### 合法的 for-in 循环

可以把初始化语句 (`i = 0`) 从 for-in 循环的头部移除。

```js
"use strict";

var obj = { a: 1, b: 2, c: 3 };

for (var i in obj) {
  console.log(obj[i]);
}
```

### 数组迭代

for...in 循环不应该应用于数组迭代中。是否考虑使用 `for` 循环而不是 `for-in` 循环来遍历数组（`Array`）？在 for 循环中是允许使用初始化语句的：

```js
var arr = ["a", "b", "c"];

for (var i = 2; i < arr.length; i++) {
  console.log(arr[i]);
}

// "c"
```

相关内容
----

* `for...in`
* `for...of` – 无论是在严格模式下还是非严格模式下也都不允许使用初始化语句。
* `for` – 更适用于数组迭代，因为允许使用初始化语句。


SyntaxError: missing ) after argument list - JavaScript

SyntaxError: missing ) after argument list
==========================================

消息
--
```

语法错误：参数列表后面缺少 )
```

错误类型
----

`SyntaxError`.

什么地方出错了？
--------

有一个函数在调用时出现错误。这可能是一个错误，丢失运算符或者转义字符等。

示例
--

因为没有使用“+”操作符来连接字符串，JavaScript 认为 `log` 函数的参数的值只是 `"PI: "`，在这种情况下，它应该用一个右括号作为结束。

```js
console.log("PI: " Math.PI);
// SyntaxError: missing ) after argument list
```

你可以正确的调用 `log` 函数通过加上“+”操作符。

```js
console.log("PI: " + Math.PI);
// "PI: 3.141592653589793"
```

相关页面
----

* Functions


TypeError: More arguments needed - JavaScript

TypeError: More arguments needed
================================

信息
--
```

TypeError: Object.create requires more than 0 arguments
TypeError: Object.setPrototypeOf requires more than 1 argument
TypeError: Object.defineProperties requires more than 0 arguments
```

错误类型
----

`TypeError`.

哪里出错了？
------

调用函数的时候出现了错误。需要提供更多的参数。

示例
--

`Object.create()` 方法要求至少有一个参数，而 `Object.setPrototypeOf()` 方法要求至少有两个参数：

```js
var obj = Object.create();
// TypeError: Object.create requires more than 0 arguments

var obj = Object.setPrototypeOf({});
// TypeError: Object.setPrototypeOf requires more than 1 argument
```

你可以将 `null` 设置为原型：

```js
var obj = Object.create(null);

var obj = Object.setPrototypeOf({}, null);
```

相关
--

* Functions


SyntaxError: "0"-prefixed octal literals and octal escape seq. are deprecated - JavaScript

SyntaxError: "0"-prefixed octal literals and octal escape seq. are deprecated
=============================================================================

错误提示
----
```

SyntaxError:
"0"-prefixed octal literals and octal escape sequences are deprecated;
for octal literals use the \"0o\" prefix instead
```

错误类型
----

语法错误（`SyntaxError` ），只出现于严格模式下。

哪里出错了？
------

八进制字面量与八进制转义序列语法已经被废弃，在严格模式下会报语法错误（`SyntaxError`）。在 ECMAScript 2015 及以后的规范中，标准语法是前导 0 后面跟一个大写或小写的拉丁文字母 "O" (`0o` 或 `0O)`。

示例
--

### 前导"0"形式的八进制字面量

```js
"use strict";

03;

// SyntaxError: "0"-prefixed octal literals and octal escape sequences
// are deprecated
```

### 八进制转义序列

```js
"use strict";

"\251";

// SyntaxError: "0"-prefixed octal literals and octal escape sequences
// are deprecated
```

### 合法的八进制数字

使用前导 0 后面跟字母 "o" 或 "O" 的形式：

```js
0o3;
```

至于八进制转义序列，你可以使用十六进制转义序列来代替：

```js
"\xA9";
```

参见
--

* Lexical grammar


TypeError: invalid 'instanceof' operand 'x' - JavaScript

TypeError: invalid 'instanceof' operand 'x'
===========================================

消息
--
```

TypeError: invalid 'instanceof' operand "x" (Firefox)
TypeError: "x" is not a function (Firefox)
TypeError: Right-hand side of 'instanceof' is not an object (Chrome)
TypeError: Right-hand side of 'instanceof' is not callable (Chrome)
```

错误类型
----

`TypeError`哪里出错了？
------

`instanceof` 操作符 希望右边的操作数为一个构造对象，即一个有 `prototype` 属性且可以调用的对象。

示例
--

```js
"test" instanceof ""; // TypeError: invalid 'instanceof' operand ""
42 instanceof 0; // TypeError: invalid 'instanceof' operand 0

function Foo() {}
var f = Foo(); // Foo() is called and returns undefined
var x = new Foo();

x instanceof f; // TypeError: invalid 'instanceof' operand f
x instanceof x; // TypeError: x is not a function
```

为了解决上述问题，你可能需要将`instanceof` 操作符 换成 `typeof` 操作符，或者确保你使用的是函数名称，而不是函数计算的结果。

```js
typeof "test" == "string"; // true
typeof 42 == "number"; // true

function Foo() {}
var f = Foo; // Do not call Foo.
var x = new Foo();

x instanceof f; // true
x instanceof Foo; // true
```

参见
--

* `instanceof` 操作符
* `typeof` 操作符


Warning: -file- is being assigned a //# sourceMappingURL, but already has one - JavaScript

Warning: -file- is being assigned a //# sourceMappingURL, but already has one
=============================================================================

消息
--
```

Warning: -file- is being assigned a //# sourceMappingURL, but already has one.
```

错误类型
----

一个警告。JavaScript 的执行不会中止。

哪里有问题？
------

对于给定的 JavaScript 源码，源码映射规定了不止一次。

JavaScript 源码通常被组合和压缩，使其从服务器传递更加高效。使用了源码映射，调试器能够将执行的源码映射到原始的源码。有两种指派源码映射的方式，通过注释，或者对 JavaScript 设置标题。

示例
--

使用文件中的注释来设置源码映射：

```js
//# sourceMappingURL=http://example.com/path/to/your/sourcemap.map
```

或者，你可以对你的 JavaScript 文件设置一个标题：

```js
X-SourceMap: /path/to/file.js.map
```

另见
--

* 如何使用源码映射 – Firefox Tools documentation
* 源码映射简介 – HTML5 rocks


ReferenceError: reference to undefined property "x" - JavaScript

ReferenceError: reference to undefined property "x"
===================================================

当脚本尝试去访问一个不存在的对象属性时，就会出现 JavaScript 警告“reference to undefined property”。

消息
--
```

ReferenceError: reference to undefined property "x" (Firefox)
```

错误类型
----

（仅限 Firefox）仅在 `javascript.options.strict` 首选项设置为 `true` 的情况下会出现 `ReferenceError` 警告。

哪里出错了？
------

脚本尝试去访问一个不存在的对象属性。有两种方法可以访问属性，请参阅属性访问器参考页以获取更多信息。

示例
--

### 无效的

本例中，`bar` 属性是未定义的，因此会出现 `ReferenceError`。

```js
const foo = {};
foo.bar; // ReferenceError: reference to undefined property "bar"
```

### 有效的

为了避免错误，你需要向对象添加 `bar` 的定义或在尝试访问 `bar` 属性之前检查 `bar` 属性是否存在；可以使用 `in` 运算符或 `Object.hasOwn()` 方法来实现，如下所示：

```js
const foo = {};

// 定义 bar 属性

foo.bar = "moon";
console.log(foo.bar); // "moon"

// 在访问 bar 属性之前测试其是否存在

if (Object.hasOwn(foo, "bar")) {
  console.log(foo.bar);
}
```

参见
--

* 属性访问器


SyntaxError: "x" is a reserved identifier - JavaScript

SyntaxError: "x" is a reserved identifier
=========================================

消息提示
----
```

SyntaxError: "x" is a reserved identifier (Firefox)
SyntaxError: Unexpected reserved word (Chrome)
```

错误类型
----

`SyntaxError`哪里出错了？
------

保留字 用作标记符将会出错。这些标记符在严格模式和非严格模式下保留：

* `enum`

以下标记符只会在严格模式下才作为保留字：

* `implements`
* `interface`
* `let`
* `package`
* `private`
* `protected`
* `public`
* `static`
示例
--

### 严格与非严格模式下的保留字

在两种模式下，`enum` 标识符都会作为保留字。

```js
var enum = { RED: 0, GREEN: 1, BLUE: 2 };
// SyntaxError: enum is a reserved identifier
```

在严格模式下，会有更多的保留字。

```js
"use strict";
var package = ["potatoes", "rice", "fries"];
// SyntaxError: package is a reserved identifier
```

你需要对上述变量重新命名。

```js
var colorEnum = { RED: 0, GREEN: 1, BLUE: 2 };
var list = ["potatoes", "rice", "fries"];
```

### 升级旧版本浏览器

假如你还在使用尚未支持 let 或 class 等特性的旧版本浏览器，你应该将它们升级到支持这些新语言特性的版本。

```js
"use strict";
class DocArchiver {}

// SyntaxError: class is a reserved identifier
//（只会在旧版本浏览器中抛出，例如 Firefox 44 或更老的版本）
```

相关内容
----

* Good variable names


SyntaxError: missing = in const declaration - JavaScript

SyntaxError: missing = in const declaration
===========================================

错误提示
----
```

SyntaxError: missing = in const declaration (Firefox)
SyntaxError: Missing initializer in const declaration (Chrome)
```

错误类型
----

`SyntaxError`哪里出错了？
------

常量指的是在程序正常运行过程中不能被修改的值。它的值不能通过二次赋值来改变，同时也不能被再次声明。在 JavaScript 中，常量在声明时使用 `const` 关键字来修饰。常量需要初始化器；也就是说，必须在声明的同时为其赋值（鉴于常量值指定之后不能再进行修改，这样做是容易理解的）。

示例
--

### 初始值缺失

不同于 var 或 let 关键字，必须在常量声明中为其赋值。下面的例子中会报错：

```js
const COLUMNS;
// SyntaxError: missing = in const declaration
```

### 错误修正

修正这个问题的方法有很多种。仔细检查对于问题中的常量，你想要达到什么目标。

#### 添加常量值

在声明语句中为其赋值：

```js
const COLUMNS = 80;
```

#### `const`, `let` 还是 `var?`

如果你并不想声明一个常量值，那么就不要使用 const 关键字。或许你想要的是使用 `let` 来声明一个块状作用域变量或者是用 `var` 声明一个全局变量。这两者都不需要设置初始值。

```js
let columns;
```

相关内容
----

* `let`
* `var`


ReferenceError: invalid assignment left-hand side - JavaScript

ReferenceError: invalid assignment left-hand side
=================================================

Message
-------
```

ReferenceError: invalid assignment left-hand side
```

Error type
----------

`ReferenceError`.

What went wrong?
----------------

有时会出现不可预料的赋值情况。这可能是因为赋值运算符 (en-US)或比较运算符 (en-US)不匹配的缘故。正确的是，使用“=”号将值赋给一个变量，使用“==”或者“===”来比较一个值。

Examples
--------

```js
if (Math.PI = 3 || Math.PI = 4) {
  console.log('no way!');
}
// ReferenceError: invalid assignment left-hand side

var str = 'Hello, '
+= 'is it me '
+= 'you\'re looking for?';
// ReferenceError: invalid assignment left-hand side
```

在 `if` 语句中，你要使用比较运算符 ("==")，而在字符串连接中，使用加号运算符 ("+")。

```js
if (Math.PI == 3 || Math.PI == 4) {
  console.log("no way!");
}

var str = "Hello, " + "from the " + "other side!";
```

See also
--------

* 赋值运算符 (en-US)
* 比较运算符 (en-US)


SyntaxError: Unexpected token - JavaScript

SyntaxError: Unexpected token
=============================

信息
--
```

SyntaxError: expected expression, got "x"
SyntaxError: expected property name, got "x"
SyntaxError: expected target, got "x"
SyntaxError: expected rest argument name, got "x"
SyntaxError: expected closing parenthesis, got "x"
SyntaxError: expected '=>' after argument list, got "x"
```

错误类型
----

`SyntaxError`哪里出错了？
------

期望获得一个特定的语法结构，但得到了其他的。可能只是一个简单的错字。

示例
--

### 期望的表达式

例如，在调用函数时，不允许使用尾随逗号。有尾逗号的时候，JavaScript 会期望有另一个参数，可以是任何表达式。

```js
Math.max(2, 42,);
// SyntaxError: expected expression, got ')'
```

正确的方法是省略最后一个逗号或添加另一个参数：

```js
Math.max(2, 42);
Math.max(2, 42, 13 + 37);
```

相关
--

* `Math.max()`


SyntaxError: illegal character - JavaScript

SyntaxError: illegal character
==============================

错误提示
----
```

SyntaxError: illegal character (Firefox)
SyntaxError: Invalid or unexpected token (Chrome)
```

错误类型
----

`SyntaxError`哪里出错了？
------

在代码中有非法的或者不期望出现的标记符号出现在不该出现的位置。请使用支持语法高亮功能的编辑器仔细检查你的代码，看看是否存在张冠李戴的情况，比如减号 (`-`) 与连接符 (`–`) ，或者是英文双引号 (`"`) 与中文双引号 (`“`)。

示例
--

### 错配字符

一些字符看起来会很相像，但是会导致于语法解析器解析代码失败。

```js
“This looks like a string”;
// SyntaxError: illegal character

42 – 13;
// SyntaxError: illegal character
```

下面这样是可以正常运行的：

```js
"This is actually a string";

42 - 13;
```

### 遗漏的字符

很容易就会在这里或那里遗漏一些字符。

```js
var colors = ['#000', #333', '#666'];
// SyntaxError: illegal character
```

把遗漏的引号给 '#333' 添加上。

```js
var colors = ["#000", "#333", "#666"];
```

### 隐藏字符

当从外部复制粘贴代码的时候，有可能就有非法的隐藏字符的存在，需要引起注意！

```js
var foo = 'bar';
// SyntaxError: illegal character
```

当使用文本编辑器如 VIM 进行探测的时候，可以发现这里存在一个零宽空格 (ZWSP) (U+200B)。

```js
var foo = 'bar';<200b>
```

相关内容
----

* Lexical grammar


RangeError: argument is not a valid code point - JavaScript

RangeError: argument is not a valid code point
==============================================

JavaScript 异常“Invalid code point”会在 `String.fromCodePoint()` 方法与 `NaN` 值、负整数（-1）、非整数（5.4）或大于 0x10FFFF（1114111）的值一起使用时抛出。

错误信息
----
```

RangeError: Invalid code point -1 (V8-based)
RangeError: -1 is not a valid code point (Firefox)
RangeError: Arguments contain a value that is out of range of code points (Safari)
```

错误类型
----

`RangeError`什么地方出错了？
--------

`String.fromCodePoint()` 方法在被传入 `NaN` 值、负整数（-1）、非整数（5.4）或大于 0x10FFFF 的值时抛出该错误。

码位（code point）是 Unicode 代码空间中的数值，即范围为 `0` 到 `0x10FFFF` 的整数。

示例
--

### 无效的示例

```js
String.fromCodePoint("\_"); // RangeError
String.fromCodePoint(Infinity); // RangeError
String.fromCodePoint(-1); // RangeError
String.fromCodePoint(3.14); // RangeError
String.fromCodePoint(3e-2); // RangeError
String.fromCodePoint(NaN); // RangeError
```

### 有效的示例

```js
String.fromCodePoint(42); // "\*"
String.fromCodePoint(65, 90); // "AZ"
String.fromCodePoint(0x404); // 'Є' (U+0404)
String.fromCodePoint(0x2f804); // '你' (U+2F804)
String.fromCodePoint(194564); // '你'
String.fromCodePoint(0x1d306, 0x61, 0x1d307); // '𝌆a𝌇'
```

参见
--

* `String.fromCodePoint()`


SyntaxError: unterminated string literal - JavaScript

SyntaxError: unterminated string literal
========================================

信息
--
```

SyntaxError: unterminated string literal
```

错误类型
----

`SyntaxError`哪里出错了？
------

某处 js 解析字符串出错。字符串必须使用单引号或双引号来正确的关闭。在 Javascript 中使用单引号的字符和双引号的字符串是没有区别的。字符串用转义字符不是单引号就是双引。为解决这个错误，检查一下：

* 你字符串的引号是否成对。
* 你是否正确使用了转义序列
* 你的字符串是否在多行中解析正常。
示例
--

### 多行字符串

在 javascript 中你不能够直接使用多行字符串赋值给一个变量。如下：

```js
var longString = "This is a very long string which needs
                  to wrap across multiple lines because
                  otherwise my code is unreadable.";
// SyntaxError: unterminated string literal
```

可以使用"+"运算符 (en-US)，反斜杠，或模板字符串来代替多行。“+”运算符的使用如下：

```js
var longString =
  "This is a very long string which needs " +
  "to wrap across multiple lines because " +
  "otherwise my code is unreadable.";
```

或者你可以使用“\”在每一行的末尾，以表示该字符串在下一行继续。要确保“\“之后没有没有空格和任何其他的字符，及缩进，否则该“\”将不会起作用。使用方法如下：

```js
var longString =
  "This is a very long string which needs \
to wrap across multiple lines because \
otherwise my code is unreadable.";
```

另一种方式是使用 ES 2015 的环境所支持模板字符串（反引号` `）。

```js
var longString = `This is a very long string which needs
 to wrap across multiple lines because
 otherwise my code is unreadable.`;
```

相关
--

* `String`
* 模板字符串


SyntaxError: missing ) after condition - JavaScript

SyntaxError: missing ) after condition
======================================

错误提示
----
```

SyntaxError: missing ) after condition
```

错误类型
----

`SyntaxError`哪里出错了？
------

这个错误与 if 条件语句是如何写的有关。在任何编程语言中，代码都需要做出一些判断，然后根据不同的判断结果来执行不同的操作。if 语句会在其指定的判断条件为真的时候执行。在 JavaScript 中，条件表达式必须出现在 if 关键字后面的一对括号中，像下面这样：

```js
if (condition) {
  // do something if the condition is true
}
```

示例
--

下面这种情况的出现可能只是出于大意，需要仔细检查代码中的括号。

```js
if (3 > Math.PI {
  console.log("wait what?");
}

// SyntaxError: missing ) after condition
```

修复代码的方法就是添加闭合条件表达式的右括号。

```js
if (3 > Math.PI) {
  console.log("wait what?");
}
```

如果你是从其他语言转到 JavaScript 的，那么很容易在 JavaScript 中使用与之含义不同或者没有任何意义的关键字。

```js
if (done is true) {
 console.log("we are done!");
}

// SyntaxError: missing ) after condition
```

相反你需要使用正确的比较操作符 (en-US)，如下：

```js
if (done === true) {
  console.log("we are done!");
}
```

相关内容
----

* `if...else`
* 比较操作符 (en-US)
* 在代码中做判断 — 条件表达式


TypeError: "x" is not a constructor - JavaScript

TypeError: "x" is not a constructor
===================================

信息
--
```

TypeError: "x" is not a constructor

TypeError: Math is not a constructor
TypeError: JSON is not a constructor
TypeError: Symbol is not a constructor
TypeError: Reflect is not a constructor
TypeError: Intl is not a constructor
TypeError: SIMD is not a constructor
TypeError: Atomics is not a constructor
```

错误类型
----

`TypeError`哪里出错了？
------

是因为尝试将不是构造器的对象或者变量来作为构造器使用。参考 constructor 或者 `new` operator 来了解什么是构造器。

有很多的全局对象比如 `String`、`Array` 等等都是可以使用 `new` 操作符的构造器。但是有一些全局对象并不是，且其属性和方法都是静态 的。下面的 JavaScript 标准内置对象都不是构造器：`Math`，`JSON`，`Symbol`，`Reflect`，`Intl`，`SIMD`，`Atomics`。

Generator functions 也不能作为构造器来使用。

示例
--

### 无效的

```js
var Car = 1;
new Car();
// TypeError: Car is not a constructor

new Math();
// TypeError: Math is not a constructor

new Symbol();
// TypeError: Symbol is not a constructor

function\* f() {}
var obj = new f();
// TypeError: f is not a constructor
```

### 一个构造器

假设你想为汽车创建一个对象类型。你希望此类型的对象被称为 `car`，并且你希望它具有 make，model 和 year 属性。为此，你编写以下函数：

```js
function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
```

现在你可以创建一个名为 `mycar` 的对象，如下所示：

```js
var mycar = new Car("Eagle", "Talon TSi", 1993);
```

### 关于 Promises

当返回了一个 immediately-resolved 或者 immediately-rejected Promise 的时候，你根本不需要去创建、操作一个新的 Promise 对象。

这是不合法的（Promise constructor 被错误的调用了）且会抛出一个 错误 `TypeError: this is not a constructor` exception:

```js
return new Promise.resolve(true);
```

使用 Promise.resolve() 或者 Promise.reject() 静态方法来代替：

```js
// 这是合法的，但是没必要这么长：
return new Promise((resolve, reject) => {
  resolve(true);
});

// 用静态方法来代替：
return Promise.resolve(true);
return Promise.reject(false);
```

参见
--

* constructor
* `new` 运算符


RangeError: repeat count must be less than infinity - JavaScript

RangeError: repeat count must be less than infinity
===================================================

信息
--
```

RangeError: repeat count must be less than infinity and not overflow maximum string size (Firefox)

RangeError: Invalid count value (Chrome)
```

错误类型
----

`RangeError`发生了什么？
------

代码中使用了 `String.prototype.repeat()`方法。它有一个计数参数，表示重复该字符串的次数。该参数必须在 0 及正 `Infinity` 之间，且不能为负数。该值的合法范围可以这样表示： [0, +∞)。

其结果字符串也不能长于最大字符串，不同 JavaScript 引擎中可能有所不同。在 Firefox (SpiderMonkey) 里最大字符串大小为 2^28 -1 (`0xFFFFFFF`)。

示例
--

### 无效的

```js
"abc".repeat(Infinity); // RangeError
"a".repeat(2 \*\* 28); // RangeError
```

### 有效的

```js
"abc".repeat(0); // ''
"abc".repeat(1); // 'abc'
"abc".repeat(2); // 'abcabc'
"abc".repeat(3.5); // 'abcabcabc' (count will be converted to integer)
```

See also
--------

* `String.prototype.repeat()`


RangeError: invalid date - JavaScript

RangeError: invalid date
========================

消息
--
```

范围错误：非法数据 (Firefox)
范围错误：非法时间值 (Chrome)
范围错误：提供的数据不是有效的 (Chrome)
```

错误类型
----

`RangeError`哪里出错了？
------

为 `Date` 或 `Date.parse()` 提供了一个会导致无效日期的字符串。

示例
--

### 错误示例

ISO 格式化字符串中不可识别的字符串或者包含非法元素值的日期一般会返回 `NaN`。然而，根据实现的不同，不符合 ISO 格式的字符串可能也会抛出 `RangeError: invalid date`，比如在火狐浏览器中有以下情形：

```js
new Date("foo-bar 2014");
new Date("2014-25-23").toISOString();
new Date("foo-bar 2014").toString();
```

然而下面这种情形会返回 `NaN` ：

```js
Date.parse("foo-bar 2014"); // NaN
```

参见 `Date.parse()` 文档，了解更多详情。

### 正确示例

```js
new Date("05 October 2011 14:48 UTC");
```

另见
--

* `Date`
* `Date.prototype.parse()`
* `Date.prototype.toISOString()`


TypeError: can't redefine non-configurable property "x" - JavaScript

TypeError: can't redefine non-configurable property "x"
=======================================================

错误提示
----
```

TypeError: can't redefine non-configurable property "x" (Firefox)
TypeError: Cannot redefine property: "x" (Chrome)
```

错误类型
----

`TypeError`哪里出错了？
------

这种错误的起因在于试图给对象重新定义一个属性，但是该属性是不可配置的。 `configurable` 特性控制着该属性是否可以从对象中删除，以及它的各个特性（除 writable 之外）是否可以修改。通常使用对象初始化语句定义的对象属性是可配置的。而使用 `Object.defineProperty()` 定义的属性则默认不可配置。

示例
--

### 使用 object.defineProperty 创建的不可配置属性

在使用 `Object.defineProperty()` 创建属性的时候，如果没有明确将其设定为可配置的，那么创建出来的属性就是不可配置的。

```js
var obj = Object.create({});
Object.defineProperty(obj, "foo", { value: "bar" });

Object.defineProperty(obj, "foo", { value: "baz" });
// TypeError: can't redefine non-configurable property "foo"
```

如果想要稍后重新定义的话，那么需要将 "foo" 属性设置为可配置的。

```js
var obj = Object.create({});
Object.defineProperty(obj, "foo", { value: "bar", configurable: true });
Object.defineProperty(obj, "foo", { value: "baz", configurable: true });
```

参见
--

* [[Configurable]]
* `Object.defineProperty()`


SyntaxError: return not in function - JavaScript

SyntaxError: return not in function
===================================

错误信息
----
```

SyntaxError: return not in function
SyntaxError: yield not in function
```

错误类型
----

`SyntaxError`.

什么地方出错了？
--------

`return` 返回的或者 `yield` 语句在函数 function 外被调用。或许是少了一个花括号， `return` 返回的和 `yield` 语句必须是在一个函数里，因为它们会停止（暂停或恢复）函数的继续执行，然后返回。

范例
--

```js
var cheer = function(score) {
  if (score === 147)
    return "Maximum!";
  };
  if (score > 100) {
    return "Century!";
  }
}

// SyntaxError: return not in function
// 语法错误：不是在函数里返回
```

初次看好像没什么错误，但是上面这段代码在第一个 if 后面少了一个“ { ”。正确的应该如下：

```js
var cheer = function (score) {
  if (score === 147) {
    return "Maximum!";
  }
  if (score > 100) {
    return "Century!";
  }
};
```

相关信息
----

* `return`
* `yield`


TypeError: can't delete non-configurable array element - JavaScript

TypeError: can't delete non-configurable array element
======================================================

错误提示
----
```

TypeError: can't delete non-configurable array element (Firefox)
TypeError: Cannot delete property '2' of [object Array] (Chrome)
```

错误类型
----

`TypeError`哪里出错了？
------

这个错误提示发生于当试图缩短一个数组的长度的时候，其中有元素是不可配置的（non-configurable）。正常情况下，缩短数组的长度，则超出限度的元素会被删除，而这里指的是这种操作失效的情况。

`configurable` 特性控制着属性是否可以从对象中删除，以及它的特性（除了 writable 之外）是否可以发生改变。

通常，使用数组初始化语句创建的对象是可配置的，而通过 `Object.defineProperty()` 创建的属性，默认则是不可配置的。

示例
--

### `通过 Object.defineProperty 创建的不可配置属性`

使用 `Object.defineProperty()` 且在没有明确将属性设定为可配置的情况下，默认可以创建不可配置属性。

```js
var arr = [];
Object.defineProperty(arr, 0, { value: 0 });
Object.defineProperty(arr, 1, { value: "1" });

arr.length = 1;
// TypeError: can't delete non-configurable array element
```

如果想要缩短数组长度的话，需要将其中的元素设置为可配置的。

```js
var arr = [];
Object.defineProperty(arr, 0, { value: 0, configurable: true });
Object.defineProperty(arr, 1, { value: "1", configurable: true });

arr.length = 1;
```

### `密封的数组`

`Object.seal()` 函数会将数组中现存的所有元素标记为不可配置。

```js
var arr = [1, 2, 3];
Object.seal(arr);

arr.length = 1;
// TypeError: can't delete non-configurable array element
```

（为了解决上述问题，）或者是移除 `Object.seal()` 调用，或者将数组拷贝一份。在拷贝数组的情况下，缩短备份数组的长度并不会修改原始数组的长度。

```js
var arr = [1, 2, 3];
Object.seal(arr);

// Copy the initial array to shorten the copy
var copy = Array.from(arr);
copy.length = 1;
// arr.length == 3
```

参见
--

* [[Configurable]]
* `Array.length`
* `Object.defineProperty()`
* `Object.seal()`


TypeError: cyclic object value - JavaScript

TypeError: cyclic object value
==============================

在JSON中出现循环引用时，JavaScript 会抛出 "cyclic object value" 的异常。`JSON.stringify()`并不会尝试解决这个问题，因此导致运行失败。

提示信息
----

```js
TypeError: cyclic object value (Firefox)
TypeError: Converting circular structure to JSON (Chrome and Opera)
TypeError: Circular reference in value argument not supported (Edge)
```

错误类型
----

`TypeError`哪里出错了？
------

JSON 格式本身不支持循环引用对象（尽管存在IETF 草案)，因此 `JSON.stringify()` 并不会尝试解决这个问题而是直接运行失败。

示例
--

### 循环引用

在如下循环结构中：

```js
var circularReference = { otherData: 123 };
circularReference.myself = circularReference;
```

`JSON.stringify()` 将会报错

```js
JSON.stringify(circularReference);
// TypeError: cyclic object value
```

要处理循环引用的 JSON，可以使用支持这种结构的库 (例如cycle.js))，或者自己实现，需要通过可序列化值查找、替换或者移除循环引用。

下面的代码片段演示了如何使用`JSON.stringify()`的 `replacer` 参数查找和过滤（会导致数据丢失）循环引用。

```js
const getCircularReplacer = () => {
  const seen = new WeakSet();
  return (key, value) => {
    if (typeof value === "object" && value !== null) {
      if (seen.has(value)) {
        return;
      }
      seen.add(value);
    }
    return value;
  };
};

JSON.stringify(circularReference, getCircularReplacer());
// {"otherData":123}
```

参见
--

* `JSON.stringify`
* cycle.js
 – 介绍两个方法，`JSON.decycle` 和
 `JSON.retrocycle`，这两个方法能够对循环对象引用结构进行编码和解码，并且使之成为一种扩展的且向下兼容的 JSON 格式。


TypeError: "x" is not a non-null object - JavaScript

TypeError: "x" is not a non-null object
=======================================

提示信息
----
```

TypeError: "x" is not a non-null object (Firefox)
TypeError: Property description must be an object: "x" (Chrome)
TypeError: Invalid value used in weak set (Chrome)
```

错误类型
----

`TypeError`哪里出错了？
------

在期待出现对象类型的值的地方而没有提供。`null` 不是对象类型，因此不起作用。必须在给定的场景下提供一个合适的对象。

示例
--

### 期望的属性描述器

当使用诸如 `Object.create()` 或 `Object.defineProperty()` 及{jsxref("Object.defineProperties()")}} 方法时，可选的属性描述器参数需要提供一个描述器对象。提供非对象类型的值（例如数字）将会报错：

```js
Object.defineProperty({}, "key", 1);
// TypeError: 1 is not a non-null object

Object.defineProperty({}, "key", null);
// TypeError: null is not a non-null object
```

一个合法的描述器对象类似于下面这样：

```js
Object.defineProperty({}, "key", { value: "foo", writable: false });
```

### `WeakMap` 和 `WeakSet` 对象需要对象类型的键

`WeakMap` 和 `WeakSet` 对象只能存储对象类型的键，而不能使用其他类型的。

```js
var ws = new WeakSet();
ws.add("foo");
// TypeError: "foo" is not a non-null object
```

用对象类型的值来替换：

```js
ws.add({ foo: "bar" });
ws.add(window);
```

相关内容
----

* `Object.create()`
* `Object.defineProperty()`, `Object.defineProperties()`
* `WeakMap`, `WeakSet`


SyntaxError: a declaration in the head of a for-of loop can't have an initializer - JavaScript

SyntaxError: a declaration in the head of a for-of loop can't have an initializer
=================================================================================

错误信息
----
```

SyntaxError: a declaration in the head of a for-of loop can't have an initializer (Firefox)

SyntaxError: for-of loop variable declaration may not have an initializer. (Chrome)
```

错误类型
----

`SyntaxError`哪里出错了？
------

for...of 循环的头部包含有初始化表达式。也就是对一个变量进行声明并赋值 |`for (var i = 0 of iterable)`|。这在 for-of 循环中是被禁止的。你想要的可能是允许包含初始化器的 `for` 循环形式。

示例
--

### 非法的 `for-of` 循环形式

```js
let iterable = [10, 20, 30];

for (let value = 50 of iterable) {
  console.log(value);
}

// SyntaxError: a declaration in the head of a for-of loop can't
// have an initializer
```

### 合法的 `for-of` 循环形式

需要将初始化器 (`value = 50`) 从`for-of` 循环的头部移除。或许你的本意是给每个值添加 50 的偏移量，在这种情况下，可以在循环体中进行添加。

```js
let iterable = [10, 20, 30];

for (let value of iterable) {
  value += 50;
  console.log(value);
}
// 60
// 70
// 80
```

相关内容
----

* `for...of`
* `for...in` – 在严格模式下也同样禁止使用初始化器 (SyntaxError: for-in loop head declarations may not have initializers)
* `for` – 在迭代时允许定义初始化器


TypeError: "x" is not a function - JavaScript

TypeError: "x" is not a function
================================

JavaScript 异常"is not a function"会在试图去调用一个像函数一样的值，但是该值实际上不是函数时被抛出。信息
--
```

TypeError: Object doesn't support property or method {x} (Edge)
TypeError: "x" is not a function
```

错误类型
----

`TypeError`哪里出错了？
------

问题出在你试图去调用一个像函数一样的值，但是该值实际上不是函数，有时候你的代码需要调用一些函数，但是那种值并不能当作函数来被调用。

也许函数名称上有错别字？也许你正在调用 Object 对象没有这个方法？例如，在 JavaScript 中单纯的对象 (Object) 没有**map**函数，但是 JavaScript 数组 (Array) 对象却有这个函数。

再比如，在 JavaScript 中很多原生对象的内置方法需要你提供一个（回调）函数。所以你必须提供一个函数，以使这些方法正常工作：

* 当你在使用 `Array` 或 `TypedArray` 对象时：
    + `Array.prototype.every()`, `Array.prototype.some()`, `Array.prototype.forEach()`, `Array.prototype.map()`, `Array.prototype.filter()`, `Array.prototype.reduce()`, `Array.prototype.reduceRight()`, `Array.prototype.find()`
* 当你在使用 `Map` 和 `Set` 对象时：
    + `Map.prototype.forEach()` and `Set.prototype.forEach()`
示例
--

### 函数的名称错误

函数的名称拼写错误，这种情况是经常发生的：

```js
var x = document.getElementByID("foo");
// TypeError: document.getElementByID is not a function
```

正确的方法名应该是 `getElementById：`

```js
var x = document.getElementById("foo");
```

### 调用 Object 类型中不存在的方法

对于某些特殊的方法，它只属于某些特定的原生对象中，你必须提供一个回调函数才能正常运行。例如：这里调用了一个 `Array.prototype.map()` 方法，但是这方法只能被 `Array` 对象所调用。

```js
var obj = { a: 13, b: 37, c: 42 };

obj.map(function (num) {
  return num \* 2;
});

// TypeError: obj.map is not a function
```

正确的做法，使用一个数组来代替：

```js
var numbers = [1, 4, 9];

numbers.map(function (num) {
  return num \* 2;
});

// Array [ 2, 8, 18 ]
```

### 函数与已有属性重名

当你在创建类时，可能会存在某个属性和某个方法的名称相同，当你在调用该函数时，编译器会认为该函数不存在。

```js
var Dog = function () {
  this.age = 11;
  this.color = "black";
  this.name = "Ralph";
  return this;
};

Dog.prototype.name = function (name) {
  this.name = name;
  return this;
};

var myNewDog = new Dog();
myNewDog.name("Cassidy"); //Uncaught TypeError: myNewDog.name is not a function
```

正确的做法是使用不同的变量名。

```js
var Dog = function () {
  this.age = 11;
  this.color = "black";
  this.dogName = "Ralph"; //Using this.dogName instead of .name
  return this;
};

Dog.prototype.name = function (name) {
  this.dogName = name;
  return this;
};

var myNewDog = new Dog();
myNewDog.name("Cassidy"); //Dog { age: 11, color: 'black', dogName: 'Cassidy' }
```

### 使用括号进行乘法运算

在数学中，你可以将 2 × (3 + 5) 写为 2\*(3 + 5) 或者省略为 2(3 + 5).

使用后者时将会抛出错误：

```js
const sixteen = 2(3 + 5);
alert("2 x (3 + 5) is " + String(sixteen));
//Uncaught TypeError: 2 is not a function
```

你可以添加乘法运算符 `*` 来改正代码：

```js
const sixteen = 2 \* (3 + 5);
alert("2 x (3 + 5) is " + String(sixteen));
//2 x (3 + 5) is 16
```

### 正确地导入和导出模块

确保正确导入模块。

以下为一个示例模块 (`helpers.js`)
```

let helpers = function () { };

helpers.groupBy = function (objectArray, property) {
  return objectArray.reduce(function (acc, obj) {
    var key = obj[property];
    if (!acc[key]) {
      acc[key] = [];
    }
    acc[key].push(obj);
    return acc;
  },
{});
}

export default helpers;
```

在 `App.js`中正确导入该模块：
```

import helpers from './helpers'
```

相关
--

* Functions


SyntaxError: missing ; before statement - JavaScript

SyntaxError: missing ; before statement
=======================================

信息
--
```

SyntaxError: Expected ';' (Edge)
```

```
 SyntaxError: missing ; before statement (Firefox)
```

错误类型
----

`SyntaxError`.

哪里出错了？
------

某个地方丢失了一个 (`;`)。 JavaScript 语句必须以分号结束。有一些是由 自动分号插入 (ASI) 的使用所影响到的，但在这种情况下，你需要提供一个分号，以便于 JavaScript 可以将源代码解析正确。然而，通常情况下，这个错误只是另一个错误一个导致的，如不正确转义字符串，使用 var 的错误。你也可能有太多的括号的地方。当出现此错误时，仔细检查语法。

示例
--

转义字符串

这个错误可能发生不正确时容易转义字符串 JavaScript 引擎是希望你的字符串的末尾已经。例如：

```js
var foo = 'Tom's bar';
// SyntaxError: missing ; before statement
```

你可以用双引号，或者用\转义：

```js
var foo = "Tom's bar";
var foo = 'Tom\'s bar';
```

### 用 var 声明属性

你不能将带有变量声明的对象或数组的属性用`var`来声明。

```js
var obj = {};
var obj.foo = "hi"; // SyntaxError missing ; before statement

var array = [];
var array[0] = "there"; // SyntaxError missing ; before statement
```

而是省略掉`var`关键词：

```js
var obj = {};
obj.foo = "hi";

var array = [];
array[0] = "there";
```

### 不推荐使用的关键字

如果你用的是另一种编程语言，那么在 javaScript 中使用不具有相同或完全没有意义的关键字也是很常见的：

```js
def print(info){
  console.log(info);
}; // SyntaxError missing ; before statement
```

因此，建议使用`function`而不是`def`：

```js
function print(info) {
  console.log(info);
}
```

参考
--

* 自动分号插入 (ASI)
* JavaScript 语句


ReferenceError: deprecated caller or arguments usage - JavaScript

ReferenceError: deprecated caller or arguments usage
====================================================

信息
--
```

Warning: ReferenceError: deprecated caller usage (Firefox)
Warning: ReferenceError: deprecated arguments usage (Firefox)
TypeError: 'callee' and 'caller' cannot be accessed in strict mode. (Safari)
```

错误类型
----

仅在严格模式下出现的 `ReferenceError` 警告。JavaScript 的执行将不会停止。

发生了什么？
------

在 strict mode 中，`Function.caller` 和 `Function.arguments` 属性是不该使用的。它们都是已经被废弃的了，因为这两者泄露了函数的调用者，是不标准的，难于优化和有这潜在的性能问题。

实力
--

### 废弃的 `function.caller` or `arguments.callee.caller`

`Function.caller` 和 `arguments.callee.caller` 都是已废弃的 (详见参考文章)。

```js
"use strict";

function myFunc() {
  if (myFunc.caller == null) {
    return "The function was called from the top!";
  } else {
    return "This function's caller was " + myFunc.caller;
  }
}

myFunc();
// Warning: ReferenceError: deprecated caller usage
// "The function was called from the top!"
```

### `Function.arguments`

`Function.arguments` 已被废弃。 (详见参考文章)。

```js
"use strict";

function f(n) {
  g(n - 1);
}

function g(n) {
  console.log("before: " + g.arguments[0]);
  if (n > 0) {
    f(n);
  }
  console.log("after: " + g.arguments[0]);
}

f(2);

console.log("returned: " + g.arguments);
// Warning: ReferenceError: deprecated arguments usage
```

相关
--

* Deprecated and obsolete features
* Strict mode
* `Function.arguments`
* `Function.caller` and `arguments.callee.caller`


ReferenceError: "x" is not defined - JavaScript

ReferenceError: "x" is not defined
==================================

错误信息
----
```

ReferenceError: "x" is not defined
```

错误类型
----

`ReferenceError`.

什么地方出错了？
--------

在某些地方引用一个不存在的变量的时候。当你使用变量的时候，这个变量必须是已经被声明的，或者你可以确保它在你当前的脚本或作用域 (scope) 中可用。

**备注：** 当你加载一个库的时候（例如 jQuery），请确保你在这个库加载完毕后再使用这个库中的变量，如“$”。将你想加载的库的 `<script>` 标签放置在你的代码前面。

示例
--

### 变量没有被声明

```js
foo.substring(1); // ReferenceError: foo is not defined
```

“foo”变量没有在任何地方被声明。它需要是某种字符串，这样 `String.prototype.substring()` 方法才可以正常工作。

```js
var foo = "bar";
foo.substring(1); // "ar"
```

### 错误的作用域

变量必须是在它当前的执行环境中可用的。在一个函数（function）中定义的变量不能从这个函数外部的任何地方访问，因为这个变量的作用域仅在这个函数的内部。

```js
function numbers() {
  var num1 = 2,
    num2 = 3;
  return num1 + num2;
}

console.log(num1); // ReferenceError num1 is not defined.
```

然而，一个函数可用使用在它所被定义的作用域中的所有变量。换句话说，当一个函数被定义在全局作用域的时候，它可以访问所有在全局作用域中定义的变量。

```js
var num1 = 2,
  num2 = 3;

function numbers() {
  return num1 + num2;
}

console.log(num1); // 2
```

相关页面
----

* Scope
* Declaring variables in the JavaScript Guide
* Function scope in the JavaScript Guide


RangeError: radix must be an integer - JavaScript

RangeError: radix must be an integer
====================================

消息
--
```

RangeError: radix must be an integer at least 2 and no greater than 36 (Firefox)
RangeError: toString() radix argument must be between 2 and 36 (Chrome)
```

错误类型
----

`RangeError`发生了什么错误？
--------

在使用`Number.prototype.toString()`方法时使用了可选的基数参数，参数应该为一个 2 到 36 之间的整型 (数字)，返回对应数字的转换为字符串时表示的该进制对应的数字量。

为什么小于 36 呢？因为一个大于 (包含等于)10 的基数在使用时需要用一个字母表字符来代替。不能超过 36 是因为拉丁字母表中只有 26 个字符。

你可能会用到以下的常见基数：

* 2 for 二进制,
* 8 for 八进制,
* 10 for 十进制,
* 16 for 十六进制.
示例
--

### 错误示例

```js
(42).toString(0);
(42).toString(1);
(42).toString(37);
(42).toString(150);
// You cannot use a string like this for formatting:
(12071989).toString("MM-dd-yyyy");
```

### 正确示例

```js
(42).toString(2); // "101010" (binary)
(13).toString(8); // "15" (octal)
(0x42).toString(10); // "66" (decimal)
(100000).toString(16); // "186a0" (hexadecimal)
```

参考
--

* `Number.prototype.toString()`


SyntaxError: missing variable name - JavaScript

SyntaxError: missing variable name
==================================

错误提示
----
```

SyntaxError: missing variable name (Firefox)
SyntaxError: Unexpected token = (Chrome)
```

错误类型
----

`SyntaxError`哪里出错了？
------

缺失变量名。这有很大的可能性是由你的代码中的语法错误造成的。也许是什么地方的逗号出了问题，或者是你正在绞尽脑汁想一个合适的名字。完全可以理解！为变量起名确实让人头疼。

示例
--

### 变量名缺失

```js
var = "foo";
```

为变量起一个合适的明确确实不是一件容易的事情。这种经历每个人都遇到过。

```js
var ohGodWhy = "foo";
```

### 保留字不能作为变量名

有一些名称是作为保留字而存在的。不好意思，你不能使用！:(

```js
var debugger = "whoop";
// SyntaxError: missing variable name
```

### 一次性声明多个变量

在一次性声明多个变量的时候要特别留意逗号。看看是否有多余的逗号？以及是否不小心把逗号用作了分号？

```js
var x, y = "foo",
var x, = "foo"

var first = document.getElementById('one'),
var second = document.getElementById('two'),

// SyntaxError: missing variable name
```

修复后的代码：

```js
var x,
  y = "foo";
var x = "foo";

var first = document.getElementById("one");
var second = document.getElementById("two");
```

### 数组

在 JavaScript 中 `Array` 字面量需要使用方括号将值包裹起来。下面这样是不对的：

```js
var arr = 1,2,3,4,5;
// SyntaxError: missing variable name
```

这样写才是正确的：

```js
var arr = [1, 2, 3, 4, 5];
```

相关内容
----

* Good variable names
* `var`
* Variable declarations in the JavaScript Guide


TypeError: property "x" is non-configurable and can't be deleted - JavaScript

TypeError: property "x" is non-configurable and can't be deleted
================================================================

消息
--
```

TypeError: property "x" is non-configurable and can't be deleted. (Firefox)
TypeError: Cannot delete property 'x' of #<Object> (Chrome)
```

错误类型
----

`TypeError` 只出现在严格模式下。

哪里有问题？
------

尝试删除某个属性，但是这个属性是不可配置的。`configurable` 属性控制是否该属性能从对象上删除，以及它的属性（除了`writable`）能否被修改。

这个错误仅仅在严格模式下出现。在非严格模式下，这个操作返回 `false`。

示例
--

不可配置的属性并不特别常见，但是它们可以使用 `Object.defineProperty()` 或 `Object.freeze()` 创建。

```js
"use strict";
var obj = Object.freeze({ name: "Elsa", score: 157 });
delete obj.score; // TypeError

("use strict");
var obj = {};
Object.defineProperty(obj, "foo", { value: 2, configurable: false });
delete obj.foo; // TypeError

("use strict");
var frozenArray = Object.freeze([0, 1, 2]);
frozenArray.pop(); // TypeError
```

也有一些内建于 JavaScript 的不可配置属性。你可能会尝试删除一个数学常量。

```js
"use strict";
delete Math.PI; // TypeError
```

另见
--

* delete operator
* `Object.defineProperty()`
* `Object.freeze()`


Warning: unreachable code after return statement - JavaScript

Warning: unreachable code after return statement
================================================

当在 `return` 语句之后使用别的语句，或在无分号返回语句之后直接在后面跟随表达式，会出现 JavaScript 警告“unreachable code after return statement”。

信息
--
```

Warning: unreachable code after return statement (Firefox)
```

错误类型
----

警告

什么地方出错了？
--------

在 `return` 语句之后的不可达的语句会在下列情形中产生：

* 在 `return` 语句之后出现其他表达式；
* 在省略分号的 return 语句之后直接跟随一个表达式。

当一个表达式出现在一个有效的 `return` 表达式之后时，会出现这个警告，用以说明在 `return` 语句之后的表达式不可达，即这条语句之后的表达式永远不会运行。

为什么需要在 `return` 语句之后添加分号？在省略分号的 `return` 语句之后，开发者想要终止当前函数的执行还是返回 return 之后表达式的结果的意图是不明确的。这个警告表明这种情况下 `return` 语句的表述具有二义性。

当在省略分号的 return 语句之后出现下列语句时，不会出现警告：

* `throw`
* `break`
* `var`
* `function`
示例
--

### 无效的例子

```js
function f() {
  let x = 3;
  x += 4;
  return x; // return 语句立即退出当前方法
  x -= 3; // 因而该语句从不会执行，即该语句为不可达语句
}

function f() {
  return; // 这条语句被视作 `return;`
  3 + 4; // 因而此处该函数已经返回，该语句永不会执行
}
```

### 有效的例子

```js
function f() {
  let x = 3;
  x += 4;
  x -= 3;
  return x; // OK: 执行完成所有语句之后返回
}

function f() {
  return 3 + 4; // OK: 省略分号的 return 语句与执行的表达式在同一行
}
```

参见
--

* 自动插入分号


Unicode property escapes - JavaScript

Unicode property escapes
========================

**Unicode property escapes** 正则表达式 支持根据 Unicode 属性进行匹配，例如我们可以用它来匹配出表情、标点符号、字母（甚至适用特定语言或文字）等。同一符号可以拥有多种 Unicode 属性，属性则有 binary ("boolean-like") 和 non-binary 之分。

尝试一下
----

**备注：** 使用 Unicode 属性转义依靠 `\u` 标识，`\u` 表示该字符串被视为一串 Unicode 代码点。参考 `RegExp.prototype.unicode`。

**备注：** 某些 Unicode 属性比字符类(如 `\w` 只匹配拉丁字母 `a` 到 `z`) 包含更多的字符，但后者浏览器兼容性更好（截至 2020 一月）。

句法
--

```js
// Non-binary 属性
\p{Unicode 属性值}
\p{Unicode 属性名=Unicode 属性值}

// Binary and non-binary 属性
\p{UnicodeBinary 属性名}

// \P 为 \p 取反
\P{Unicode 属性值}
\P{UnicodeBinary 属性名}
```

* General\_Category (`gc`)
* Script (`sc`)
* Script\_Extensions (`scx`)

参考 PropertyValueAliases.txt

UnicodeBinary 属性名

Binary 属性名。E.g.: `ASCII`. `Alpha`, `Math`, `Diacritic`, `Emoji`, `Hex_Digit`, `Math`, `White_space`, 等。另见 Unicode Data PropList.txt.

Unicode 属性名

Non-binary 属性名：

Unicode 属性值

很多值有同名或简写 (e.g. 对应着 `General_Category` 属性名的属性值 `Decimal_Number` 可以写作 `Nd`, `digit`, 或 `Decimal_Number`). 大多数属性值的 `Unicode 属性名` 和等号可以省去。如果想明确某 `Unicode 属性名`，必须给出它的值。

**备注：** 因为可使用的属性和值太多，这里不一一赘述，仅提供几个例子。

基本原理
----

在 ES2018 之前，JavaScript 没有强有效的方式用匹配出不同`文字`(如马其顿语，希腊语，Georgian 等) 或不同 `属性名` (如 Emoji 等) 的字符。另见 tc39 Proposal on Unicode Property Escapes.

示例
--

### （一般类别）General categories

General categories 对 Unicode 字符进行分类，子类别用于精确定义类别。长名和简写的 Unicode 属性转义都可用。

它们可匹配字母、数字、符号、标点符号、空格等等。一般类别详见 the Unicode specification.

```js
// finding all the letters of a text
let story = "It's the Cheshire Cat: now I shall have somebody to talk to.";

// Most explicit form
story.match(/\p{General\_Category=Letter}/gu);

// It is not mandatory to use the property name for General categories
story.match(/\p{Letter}/gu);

// This is equivalent (short alias):
story.match(/\p{L}/gu);

// This is also equivalent (conjunction of all the subcategories using short aliases)
story.match(/\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}/gu);
```

### 文字（Script）和文字扩充（Script\_Extensions）

某些语言使用不同的文字，如英语和西班牙语使用拉丁文，而阿拉伯语和俄语用阿拉伯文和俄文。`Script` 和 `Script_Extensions` Unicode 属性允许正则表达式根据字符所属的`文字`或该文字所属的`文字扩充`进行匹配。

比如，`A` 属于 `拉丁文`，`ε` 属于`希腊 (Greek)`文。

```js
let mixedCharacters = "aεЛ";

// Using the canonical "long" name of the script
mixedCharacters.match(/\p{Script=Latin}/u); // a

// Using a short alias for the script
mixedCharacters.match(/\p{Script=Grek}/u); // ε

// Using the short name Sc for the Script property
mixedCharacters.match(/\p{Sc=Cyrillic}/u); // Л
```

详见 the Unicode specification 和 Scripts table in the ECMAScript specification.

某字符用于多种文字时，`Script` 优先匹配最主要使用那个字符的文字。如果想要根据非主要的文字进行匹配，我们可以使用 `Script_Extensions` 属性 (简写为`Scx`).

```js
// ٢ is the digit 2 in Arabic-Indic notation
// while it is predominantly written within the Arabic script
// it can also be written in the Thaana script

"٢".match(/\p{Script=Thaana}/u);
// null as Thaana is not the predominant script super()

"٢".match(/\p{Script\_Extensions=Thaana}/u);
// ["٢", index: 0, input: "٢", groups: undefined]
```

### Unicode 属性转义 vs. 字符类

JavaScript 正则表达式可以使用 字符类 尤其是 `\w` 或 `\d` 匹配字母或数字，然而，这样的形式只匹配拉丁文字的字符 (换言之，`a` 到 `z`、 `A` 到 `Z` 的 `\w` 和 `0` 到 `9` 的 `\d`)，见示例，这样的使用放到非拉丁文本中是有些蠢的。

Unicode 属性转义 categories 包含更多字符，`\p{Letter}` 或 `\p{Number}` 将会适用于任何文字。

```js
// Trying to use ranges to avoid \w limitations:

const nonEnglishText = "Приключения Алисы в Стране чудес";
const regexpBMPWord = /([\u0000-\u0019\u0021-\uFFFF])+/gu;
// BMP goes through U+0000 to U+FFFF but space is U+0020

console.table(nonEnglishText.match(regexpBMPWord));

// Using Unicode property escapes instead
const regexpUPE = /\p{L}+/gu;
console.table(nonEnglishText.match(regexpUPE));
```

参见
--

* Regular expressions guide
    + Character classes
    + Assertions
    + Quantifiers
    + Groups and ranges
* The `RegExp()` constructor
* `RegExp.prototype.unicode`
* Unicode character property — Wikipedia
* A blog post from Axel Rauschmayer about Unicode property escapes
* The Unicode document for Unicode properties


Introduction to using XPath in JavaScript - XPath

Introduction to using XPath in JavaScript
=========================================

该篇文档描述了如何在扩展和网站内部通过 JavaScript 调用 XPath 接口。Mozilla 实现了相当多的 DOM 3 XPath，意味着 Xpath 表达式已经可以在 HTML 和 XML 文档中使用。

使用 XPath 的主要接口是 document 对象的 evaluate 方法。

document.evaluate
-----------------

此方法针对基于 XML 的文档（包括 HTML 文档）评估 XPath 表达式，并返回 XPathResult (en-US) 对象，该对象可以是单个节点或一组节点。这个方法的现有文档位于 document.evaluate，但是对于我们现在的需求来说它相当稀疏；下面将给出更全面的研究。

```js
var xpathResult = document.evaluate(
  xpathExpression,
  contextNode,
  namespaceResolver,
  resultType,
  result,
);
```

### 参数

evaluate 函数共有五个参数：

* `xpathExpression`：包含要评估的 XPath 表达式的字符串。
* `contextNode`：应评估 `xpathExpression` 的文档中的节点，包括其任何和所有子节点。document 节点是最常用的。
* `namespaceResolver`：将传递包含在 `xpathExpression` 中的任何命名空间前缀的函数，它返回一个表示与该前缀关联的命名空间 URI 的字符串。这使得能够在 XPath 表达式中使用的前缀和文档中使用的可能不同的前缀之间进行转换。该转换函数可以是：
    + 使用 `XPathEvaluator` (en-US) 对象的 `createNSResolver` (en-US) 方法创建。
    + `null`。其可以用于 HTML 文档或者当不使用命名空间前缀时。注意，如果 `xpathExpression` 包含命名空间前缀，这将导致一个带有 `NAMESPACE_ERR` 的 `DOMException` 抛出。
    + 用户定义的函数。有关详细信息，请参阅附录中的 使用一个用户定义的命名空间解析器 部分。
* `resultType`：指定作为评估结果返回的所需结果类型的常数。最常传递的常量是 `XPathResult.ANY_TYPE`，它将返回 XPath 表达式的结果作为最自然的类型。附录中有一个部分，其中包含可用常数的完整列表。它们在下面“指定返回类型”部分中进行解释。
* `result`：如果指定了现有的 `XPathResult` 对象，它将被重用以返回结果。指定 `null` 将创建一个新的 `XPathResult` 对象。
### 返回值

返回 `xpathResult`，它是 `resultType` 参数中指定的类型的 `XPathResult` 对象。`XPathResult` 在这里定义。

### 实现默认的命名空间解析器

我们使用 document 对象的 `createNSResolver` 方法创建一个命名空间解析器。

```js
var nsResolver = document.createNSResolver(
  contextNode.ownerDocument == null
    ? contextNode.documentElement
    : contextNode.ownerDocument.documentElement,
);
```

或者，也可以使用 `XPathEvaluator` 对象的 `createNSResolver` 方法。

```js
var xpEvaluator = new XPathEvaluator();
var nsResolver = xpEvaluator.createNSResolver(
  contextNode.ownerDocument == null
    ? contextNode.documentElement
    : contextNode.ownerDocument.documentElement,
);
```

然后传递 `document.evaluate`，将 `nsResolver` 变量作为 `namespaceResolver` 参数。

注意：XPath 定义不带前缀的 QNames，以仅匹配 null 命名空间中的元素。XPath 没有办法选择应用于常规元素引用的默认命名空间（例如，`p[@id='_myid']` 对应于 `xmlns='http://www.w3.org/1999/xhtml'`）。要匹配非命名空间中的默认元素，你必须使用如 `[namespace-uri()='http://www.w3.org/1999/xhtml' and name()='p' and @id='_id']`（这种方法适用于命名空间未知的动态 XPath），或者使用前缀名测试，并创建一个命名空间解析器将前缀映射到命名空间。如果你想采取后一种方法，阅读更多关于如何创建一个用户定义的命名空间解析器。

### 注意

适应任何 DOM 节点以解析命名空间，以便可以相对于文档中出现的节点的上下文轻松地评估 XPath 表达式。此适配器的工作方式类似于 DOM 级别 3 方法 `lookupNamespaceURI` 在解析 `namespaceuRI` 时节点的层次结构中的可用的当前信息的节点。也正确解析了隐式 `xml` 前缀。

### 指定返回类型

`document.evaluate` 返回的变量 `xpathResult` 可以由单个节点（简单类型）或节点集合（节点集类型）组成。

#### 简单类型

当 `resultType` 中的所需结果类型指定为：

* `NUMBER_TYPE` - a double
* `STRING_TYPE` - a string
* `BOOLEAN_TYPE` - a boolean

我们通过分别访问 `XPathResult` 对象的以下属性来获取表达式的返回值。

* `numberValue`
* `stringValue`
* `booleanValue`

##### 示例

以下使用 XPath 表达式 `count(//p)` (en-US) 来获取 HTML 文档中的 `<p>` 元素数：

```js
var paragraphCount = document.evaluate(
  "count(//p)",
  document,
  null,
  XPathResult.ANY\_TYPE,
  null,
);

alert(
  "This document contains " +
    paragraphCount.numberValue +
    " paragraph elements",
);
```

虽然 JavaScript 允许我们将数字转换为一个字符串进行显示，但 XPath 接口不会自动转换数字结果，如果 `stringValue` 属性被请求，所以下面的代码将**不**工作：

```js
var paragraphCount = document.evaluate(
  "count(//p)",
  document,
  null,
  XPathResult.ANY\_TYPE,
  null,
);

alert(
  "This document contains " +
    paragraphCount.stringValue +
    " paragraph elements",
);
```

相反，它将返回一个带有 `NS_DOM_TYPE_ERROR` 的异常。

#### 节点集类型

`XPathResult` 对象允许以 3 种主要不同类型返回节点集：

* Iterators
* Snapshots
* First Nodes

##### Iterators

当 `resultType` 参数中的指定结果类型为：

* `UNORDERED_NODE_ITERATOR_TYPE`
* `ORDERED_NODE_ITERATOR_TYPE`

返回的 `XPathResult` 对象是一个匹配节点的节点集，它将作为迭代器，允许我们使用 `XPathResult` 的 `iterateNext()` 方法访问包含的各个节点。

一旦迭代完成所有的匹配节点，`iterateNext()` 将返回 `null`。

但请注意，如果在迭代过程中，文档发生突变（文档树被修改），将使迭代无效，并且 `XPathResult` 的 `invalidIteratorState` 属性设置为 `true`，抛出 `NS_ERROR_DOM_INVALID_STATE_ERR` 异常。

```js
var iterator = document.evaluate(
  "//phoneNumber",
  documentNode,
  null,
  XPathResult.UNORDERED\_NODE\_ITERATOR\_TYPE,
  null,
);

try {
  var thisNode = iterator.iterateNext();

  while (thisNode) {
    alert(thisNode.textContent);
    thisNode = iterator.iterateNext();
  }
} catch (e) {
  dump("Error: Document tree modified during iteration " + e);
}
```

##### Snapshots

当 `resultType` 参数中的指定结果类型为：

* `UNORDERED_NODE_SNAPSHOT_TYPE`
* `ORDERED_NODE_SNAPSHOT_TYPE`

返回的 `XPathResult` 对象是一个匹配节点的静态节点集，这允许我们通过 `XPathResult` 对象的 `snapshotItem(itemNumber)` 方法访问每个节点，其中 `itemNumber` 是要检索的节点的索引。包含的节点总数可以通过 `snapshotLength` 属性访问。

快照不随文档突变而改变，因此与迭代器不同，快照不会变得无效，但是它可能不对应于当前文档，例如节点可能已被移动，它可能包含不再存在的节点，或新节点可能已添加。

```js
var nodesSnapshot = document.evaluate(
  "//phoneNumber",
  documentNode,
  null,
  XPathResult.ORDERED\_NODE\_SNAPSHOT\_TYPE,
  null,
);

for (var i = 0; i < nodesSnapshot.snapshotLength; i++) {
  dump(nodesSnapshot.snapshotItem(i).textContent);
}
```

##### First Node

当 `resultType` 参数中的指定结果类型为：

* `ANY_UNORDERED_NODE_TYPE`
* `FIRST_ORDERED_NODE_TYPE`

返回的 `XPathResult` 对象只是匹配 XPath 表达式的第一个找到的节点。这可以通过 `XPathResult` 对象的 `singleNodeValue` 属性访问。如果节点集为空，这将为 `null`。

请注意，对于无序子类型，返回的单个节点可能不是文档顺序中的第一个，但是对于有序子类型，保证以文档顺序获取第一个匹配的节点。

```js
var firstPhoneNumber = document.evaluate(
  "//phoneNumber",
  documentNode,
  null,
  XPathResult.FIRST\_ORDERED\_NODE\_TYPE,
  null,
);

dump(
  "The first phone number found is " +
    firstPhoneNumber.singleNodeValue.textContent,
);
```

#### ANY\_TYPE 常量

当 `resultType` 参数中的结果类型指定为 `ANY_TYPE` 时，返回的 `XPathResult` 对象将是由表达式求值自然产生的任何类型。

它可以是任何简单类型（`NUMBER_TYPE`，`STRING_TYPE`，`BOOLEAN_TYPE` ），**但**如果返回的结果类型是节点集，那么它将**只**是一个 `UNORDERED_NODE_ITERATOR_TYPE`。

要在评估后确定类型，我们使用 `XPathResult` 对象的 `resultType` 属性。此属性的常量值在附录中定义。None Yet =====Any\_Type Example===== <pre> </pre>

示例
--

### 在 HTML 文档中

以下代码旨在放置在要针对其评估 XPath 表达式的 HTML 文档中内嵌或外链的任何 JavaScript 片段中。

要使用 XPath 提取 HTML 文档中的所有 `<h2>` 标题元素，`xpathExpression` 只是 `//h2`。其中，`//` 是递归下降运算符，在文档树中的任何位置将元素与 nodeName `h2` 相匹配。这个的完整代码是：link to introductory xpath doc

```js
var headings = document.evaluate(
  "//h2",
  document,
  null,
  XPathResult.ANY\_TYPE,
  null,
);
```

请注意，由于 HTML 没有命名空间，因此我们为 `namespaceResolver` 参数传递了 `null`。

因为希望在整个文档中搜索标题，所以我们使用 document 对象本身作为 `contextNode`。

此表达式的结果是 `XPathResult` 对象。如果想知道返回的结果的类型，我们可以评估返回的对象的 `resultType` 属性。在这种情况下，这将评估为 `4`，即 `UNORDERED_NODE_ITERATOR_TYPE`。这是 XPath 表达式的结果是节点集时的默认返回类型。它一次提供对单个节点的访问，并且可能不以特定顺序返回节点。要访问返回的节点，我们使用返回对象的 `iterateNext()` 方法：

```js
var thisHeading = headings.iterateNext();

var alertText = "Level 2 headings in this document are:\n";

while (thisHeading) {
  alertText += thisHeading.textContent + "\n";
  thisHeading = headings.iterateNext();
}
```

一旦迭代到一个节点，我们就可以访问该节点上的所有标准 DOM 接口。在遍历从表达式返回的所有 `h2` 元素之后，对 `iterateNext()` 的任何进一步调用都将返回 `null` 。

### 针对扩展中的 XML 文档进行评估

以下使用位于 chrome://yourextension/content/peopleDB.xml 的 XML 文档作为示例。

```xml
<?xml version="1.0"?>
<people xmlns:xul = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" >
  <person>
  <name first="george" last="bush" />
  <address street="1600 pennsylvania avenue" city="washington" country="usa"/>
  <phoneNumber>202-456-1111</phoneNumber>
  </person>
  <person>
  <name first="tony" last="blair" />
  <address street="10 downing street" city="london" country="uk"/>
  <phoneNumber>020 7925 0918</phoneNumber>
  </person>
</people>
```

为了使 XML 文档的内容在扩展中可用，我们创建一个 `XMLHttpRequest` 对象以同步加载文档，变量 `xmlDoc` 将包含该文档作为 `XMLDocument` 对象，我们可以使用 `evaluate` 方法。

JavaScript 用于扩展 xul/js 文档。

```js
var req = new XMLHttpRequest();

req.open("GET", "chrome://yourextension/content/peopleDB.xml", false);
req.send(null);

var xmlDoc = req.responseXML;

var nsResolver = xmlDoc.createNSResolver(
  xmlDoc.ownerDocument == null
    ? xmlDoc.documentElement
    : xmlDoc.ownerDocument.documentElement,
);

var personIterator = xmlDoc.evaluate(
  "//person",
  xmlDoc,
  nsResolver,
  XPathResult.ANY\_TYPE,
  null,
);
```

### 注意

当未定义 XPathResult 对象时，可以使用 `Components.interfaces.nsIDOMXPathResult.ANY_TYPE` (`CI.nsIDOMXPathResult`) 在特权代码中检索常量。类似地，可以使用以下创建 XPathEvaluator：

```js
Components.classes["@mozilla.org/dom/xpath-evaluator;1"].createInstance(
  Components.interfaces.nsIDOMXPathEvaluator,
);
```

附录
--

#### 实现用户定义的命名空间解析器

这只是一个例子。此函数将需要从 `xpathExpression` 获取命名空间前缀，并返回与该前缀对应的 URI。例如，表达式：
```

'//xhtml:td/mathml:math'
```

将选择作为 (X)HTML 表数据单元元素的子项的所有 MathML 表达式。

为了将使用命名空间 URI `http://www.w3.org/1998/Math/MathML` 的 `mathml:` 前缀和使用 URI `http://www.w3.org/1999/xhtml` 的 `xhtml:` 关联，我们提供了一个函数：

```js
function nsResolver(prefix) {
  var ns = {
    xhtml: "http://www.w3.org/1999/xhtml",
    mathml: "http://www.w3.org/1998/Math/MathML",
  };
  return ns[prefix] || null;
}
```

我们对 `document.evaluate` 的调用将如下所示：

```js
document.evaluate(
  "//xhtml:td/mathml:math",
  document,
  nsResolver,
  XPathResult.ANY\_TYPE,
  null,
);
```

#### 为 XML 文档实现默认命名空间

如前面实现默认命名空间解析器中所述，默认解析器不处理 XML 文档的默认命名空间。例如使用本文档：

```xml
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <entry />
    <entry />
    <entry />
</feed>
```

`doc.evaluate('//entry', doc, nsResolver, XPathResult.ANY_TYPE, null)` 将返回一个空集，其中 `nsResolver` 是 `createNSResolver` 返回的解析器。传递一个 `null` 解析器再好不过了。

一种可能的解决方法是创建一个自定义解析器，返回正确的默认命名空间（本例中为 Atom 命名空间）。请注意，你仍然必须在 XPath 表达式中使用一些命名空间前缀，以便解析器函数能够将其更改为所需的命名空间。例如：

```js
function resolver() {
  return "http://www.w3.org/2005/Atom";
}
doc.evaluate("//myns:entry", doc, resolver, XPathResult.ANY\_TYPE, null);
```

请注意，如果文档使用多个命名空间，则需要更复杂的解析器。

下一节将介绍一种可能更好的方法（并允许不提前知道命名空间）。

#### 使用 XPath 函数引用具有默认命名空间的元素

另一种匹配非空命名空间中的默认的元素的方法（以及对于动态 XPath 表达式很有效，其中命名空间可能未知），涉及使用如 `[namespace-uri()='http://www.w3.org/1999/xhtml' and name()='p' and @id='_myid']`。这避免了 XPath 查询无法检测到定期标记的元素上的默认命名空间的问题。

#### 获取特定的命名空间元素和属性，而不考虑前缀

如果希望在命名空间（像预期的那样）中提供灵活性，当发现命名空间元素或属性时不一定需要使用特定的前缀，必须使用特殊技术。

虽然可以修改上述部分中的方法来测试命名空间元素，而不管选择的前缀（使用 `local-name()` (en-US) 结合 `namespace-uri()` (en-US) 而不是 `name()` (en-US)），但是会发生更具挑战性的情况，如果希望在谓词中获取具有特定命名空间属性的元素（假设在 XPath 1.0 中没有与实现无关的变量）。

例如，可能尝试（不正确地）使用 namespaced 属性获取元素，如下所示： `var xpathlink = someElements[local-name(@*)="href" and namespace-uri(@*)='http://www.w3.org/1999/xlink'];`

这可能会无意中抓取一些元素，如果它的一个属性存在，本地名称为 `href`，但它是一个不同的属性，有目标（XLink）命名空间（而不是 `@href`）。

为了使用 XLink `@href` 属性（而不仅限于命名空间解析器中的预定义前缀）精确地抓取元素，可以按如下方式获取它们：

```js
var xpathEls =
  'someElements[@\*[local-name() = "href" and namespace-uri() = "http://www.w3.org/1999/xlink"]]'; // Grabs elements with any single attribute that has both the local name 'href' and the XLink namespace
var thislevel = xml.evaluate(xpathEls, xml, null, XPathResult.ANY\_TYPE, null);
var thisitemEl = thislevel.iterateNext();
```

#### XPathResult 定义的常量

| 结果类型定义的常数 | 值 | 描述 |
| ANY\_TYPE | 0 |
 包含任何类型的结果集，从表达式的评估中自然地产生。注意，如果结果是节点集，则
 UNORDERED\_NODE\_ITERATOR\_TYPE 始终是结果类型。
  |
| NUMBER\_TYPE | 1 |
 包含单个数字的结果。这非常有用，例如，在 XPath 表达式中使用
 `count()` 函数。
  |
| STRING\_TYPE | 2 | 包含单个字符串的结果。 |
| BOOLEAN\_TYPE | 3 |
 包含单个布尔值的结果。这非常有用，例如，在 XPath 表达式中使用
 `not()` 函数。
  |
| UNORDERED\_NODE\_ITERATOR\_TYPE | 4 | 包含与表达式匹配的所有节点的结果节点集。节点可能不一定与它们在文档中出现的顺序相同。 |
| ORDERED\_NODE\_ITERATOR\_TYPE | 5 | 包含与表达式匹配的所有节点的结果节点集。结果集中的节点与文档中显示的节点顺序相同。 |
| UNORDERED\_NODE\_SNAPSHOT\_TYPE | 6 | 包含与表达式匹配的所有节点的快照的结果节点集。节点可能不一定与它们在文档中出现的顺序相同。 |
| ORDERED\_NODE\_SNAPSHOT\_TYPE | 7 | 包含与表达式匹配的所有节点的快照的结果节点集。结果集中的节点与文档中显示的节点顺序相同。 |
| ANY\_UNORDERED\_NODE\_TYPE | 8 | 包含与表达式匹配的任何单个节点的结果节点集。该节点不一定是文档中与表达式匹配的第一个节点。 |
| FIRST\_ORDERED\_NODE\_TYPE | 9 | 包含文档中与表达式匹配的第一个节点的结果节点集。 |

参见
--

* Using XPath
Original Document Information
-----------------------------

* Based Upon Original Document Mozilla XPath Tutorial
* Original Source Author: James Graham.
* Other Contributors: James Thompson.
* Last Updated Date: 2006-3-25.


轴 - XPath

轴
=

XPath 规范中定义了 13 种不同的轴（axes）。轴表示与上下文节点的关系，并用于定位树上相对于该节点的节点。

有关使用 XPath 表达式的更多信息，请参阅使用 XSLT 转换 XML的扩展阅读部分，以及 xpath 规范的“axes”部分。

`ancestor`

表示上下文节点的所有祖先，从父节点开始，一直到根节点。

`ancestor-or-self`

表示上下文节点及其所有祖先，包括根节点。

`attribute`

表示上下文节点的属性。只有元素有属性。该轴可以用 at 符号（`@`）缩写。

`child`

表示上下文节点的子节点。如果 XPath 表达式没有指定轴，则默认情况下会解释为该轴。由于只有根节点或元素节点有子节点，因此任何其他用法都不会选择任何内容。

`descendant`

表示上下文节点的所有子节点，以及子节点的所有子节点，依此类推。**不**包括属性和命名空间节点——`attribute` 节点的 `parent` 是一个元素节点，但 `attribute` 节点不是其父节点的子节点。

`descendant-or-self`

表示上下文节点及其所有子节点。**不**包括属性和命名空间节点——`attribute` 节点的 `parent` 是一个元素节点，但 `attribute` 节点不是其父节点的子节点。

`following`

表示上下文节点之后出现的，除了任何 `descendant`、`attribute` 和 `namespace` 节点之外的所有节点。

`following-sibling`

表示与上下文节点具有相同父节点并在源文档中出现在上下文节点之后的所有节点。

`namespace`（*不支持*）

表示上下文节点的作用域内的所有节点。对于该轴，上下文节点必须是元素节点。

`parent`

表示上下文节点的父节点。它可以缩写为两个句点（`..`）。

`preceding`

表示文档中在上下文节点之前的，除了任何 `ancestor`、`attribute` 和 `namespace` 节点之外的所有节点。

`preceding-sibling`

表示与上下文节点具有相同父节点并在源文档中出现在上下文节点之前的所有节点。

`self`

表示上下文节点本身。它可以缩写为一个句点（`.`）。


CSS 选择器与 XPath 的对比 - XPath

CSS 选择器与 XPath 的对比
==================

本文旨在记录 CSS 选择器和 XPath 之间的区别，以便 Web 开发人员能够更好地为正确的工作选择合适的工具。

| XPath 特性 | CSS 等价形式 |
| --- | --- |
| `ancestor`、`parent` 或 `preceding-sibling` 轴 | `:has()` 选择器
实验性
 |
| `attribute` 轴 | 属性选择器 |
| `child` 轴 | 子代组合器 |
| `descendant` 轴 | 后代组合器 |
| `following-sibling` 轴 | 后续兄弟组合器或接续兄弟组合器 |
| `self` 轴 | `:scope` 或 `:host` 选择器 |


编写 MathML - MathML

编写 MathML
=========

本文解释了如何利用 MathML 语言编写数学公式。就像 HTML 或 SVG 一样，MathML 是用标签和属性描述的。当你的文档包含了较为复杂的内容时，文本会变得很冗长，因此需要适当的编写工具，例如从轻量级标记语言转换，或所见即所得的公式编辑器。有很多类似的工具可用，我们无法给出一个详尽的清单。相反，本文重点介绍常见的方法和示例。

使用 MathML
---------

即使你的 MathML 是由编辑工具生成的，也有必要了解将它们正确集成到文档中的技巧。

#### HTML 网页中的 MathML

每个 MathML 公式都由一个根元素 `math` 表示，其可以直接嵌入到 HTML 网页中。默认情况下，公式将被内联渲染，并进行额外的调整以将其高度最小化。可以使用 `display="block"` 属性，以在独立的段落中渲染复杂的公式。

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>MathML in HTML5</title>
  </head>
  <body>
    <h1>MathML in HTML5</h1>

    <p>
      One over square root of two (inline style):
      <math>
        <mfrac>
          <mn>1</mn>
          <msqrt>
            <mn>2</mn>
          </msqrt>
        </mfrac>
      </math>
    </p>

    <p>
      One over square root of two (display style):
      <math display="block">
        <mfrac>
          <mn>1</mn>
          <msqrt>
            <mn>2</mn>
          </msqrt>
        </mfrac>
      </math>
    </p>
  </body>
</html>
```

**备注：** 要在 XML 文档（例如 XHTML、EPUB 或 OpenDocument）中使用 MathML，请在每个 `<math>` 元素中放置一个 `xmlns="http://www.w3.org/1998/Math/MathML"` 属性。

**备注：** 某些电子邮件或即时通讯客户端能够发送和接收 HTML 格式的消息。因此，可以在此类消息中嵌入数学公式，只要标记清理程序未将 MathML 标签过滤掉。

#### 对不支持 MathML 的浏览器的回退方案

建议为不支持 MathML 的浏览器提供一个回退机制。如果你的文档仅包含基本的数学公式，那么一个 mathml.css 样式表可能就够了。要按条件加载它，只需要在文档的 head 中插入一行：

```html
<script src="https://fred-wang.github.io/mathml.css/mspace.js"></script>
```

如果你需要更多复杂的结构，你需要考虑使用功能更全面一些的 MathJax 库作为一个 MathML polyfill：

```html
<script src="https://fred-wang.github.io/mathjax.js/mpadded-min.js"></script>
```

或者，对于没有很好地支持 MathML 的浏览器，你也可以只在网页的顶部显示一条警告，并让用户在不同的回退方案中自主选择：

```html
<script src="https://fred-wang.github.io/mathml-warning.js/mpadded-min.js"></script>
```

**备注：** 这些脚本会执行特性检测（探测 mspace 元素和 mpadded (en-US) 元素），这优于浏览器嗅探。此外，它们是在开源许可证下分发的，因此可以自由地将它们复制到你自己的服务器上，并根据需要进行调整。

#### 数学公式字体

正如 MathML 字体 (en-US)中所解释的，数学公式字体有助于更好地渲染 MathML 的内容。因此，选择分享此类字体的安装说明 (en-US)或以 Web 字体的形式提供它们是一个不错的主意。

MathFonts 页面提供了此类 Web 字体，以及适合的样式表。例如，只要在文档 head 下插入以下内容，即可选择带有回退的 Web 字体的拉丁现代字体：

```html
<link
 rel="stylesheet"
 href="https://fred-wang.github.io/MathFonts/LatinModern/mathfonts.css" />
```

其中有多种字体，你可以选择不同的样式，例如 STIX：

```html
<link
 rel="stylesheet"
 href="https://fred-wang.github.io/MathFonts/STIX/mathfonts.css" />
```

**备注：** MathFonts 页面中的字体和样式表是在开源许可下分发的，因此可以自由地将它们复制到你自己的服务器上，并根据需要进行修改。

从简单语法转换
-------

在本节中，我们将回顾一些可以把轻量级标记语言（如，流行的 Latex 语言）转换为 MathML 的工具。

### 客户端转换

使用这种方法可以直接在网页中编写公式，JavaScript 库会负责将它们转换为 MathML。这可能是最简单的方式，但它也有一些问题：必须加载和执行额外的 JavaScript 代码，且作者必须转义保留字符；网络爬虫则无法访问 MathML 的输出……

自定义元素可用于托管这些源代码，并确保对应的 MathML 输出会通过 shadow 子树被插入和渲染 TeXZilla 的 `<la-tex>` 元素，上面的示例就可以重写成以下更简洁的样子：

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>MathML in HTML5</title>
    <script src="https://fred-wang.github.io/TeXZilla/TeXZilla-min.js"></script>
    <script src="https://fred-wang.github.io/TeXZilla/examples/customElement.js"></script>
  </head>
  <body>
    <h1>MathML in HTML5</h1>

    <p>
      One over square root of two (inline style):
      <la-tex>\frac{1}{\sqrt{2}}</la-tex>
    </p>

    <p>
      One over square root of two (display style):
      <la-tex display="block">\frac{1}{\sqrt{2}}</la-tex>
    </p>
  </body>
</html>
```

对于不熟悉 LaTex 的作者，可以使用其他的输入方法，例如 ASCIIMath 或 jqMath 语法。请记得加载 JavaScript 库并使用正确的分隔符：

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>ASCII MathML</title>
    ...
    <!-- ASCIIMathML.js -->
    <script src="/path/to/ASCIIMathML.js"></script>
    ...
    <!-- jqMath -->
    <script src="https://mathscribe.com/mathscribe/jquery-1.4.3.min.js"></script>
    <script src="https://mathscribe.com/mathscribe/jqmath-etc-0.4.6.min.js"></script>
    ...
  </head>
  <body>
    ...
    <p>One over square root of two (inline style, ASCIIMath): `1/(sqrt 2)`</p>
    ...
    <p>One over square root of two (inline style, jqMath): $1/√2$</p>
    ...
    <p>One over square root of two (display style, jqMath): $$1/√2$$</p>
    ...
  </body>
</html>
```

### 命令行程序

你可以选择命令行程序，而不是在网页加载时再生成 MathML 表达式。这样，网页中将包含静态的 MathML 内容，加载速度也会更快。考虑以下 `input.html` 网页（内容来自客户端转换）：

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>MathML in HTML5</title>
  </head>
  <body>
    <h1>MathML in HTML5</h1>

    <p>One over square root of two (inline style): $\frac{1}{\sqrt{2}}$</p>

    <p>One over square root of two (display style): $$\frac{1}{\sqrt{2}}$$</p>
  </body>
</html>
```

该网页包含了一些 `script` 标签。我们可以使用以下命令，利用 Node.js 和 TeXZilla 完成转换：

```bash
cat input.html | node TeXZilla.js streamfilter > output.html
```

在执行完成上述命令后，将创建一个包含 HTML 输出的 `output.html` 文件。以美元分隔的公式将转换为 MathML：

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>MathML in HTML5</title>
  </head>
  <body>
    <h1>MathML in HTML5</h1>

    <p>
      One over square root of two (inline style):
      <math xmlns="http://www.w3.org/1998/Math/MathML"
 ><semantics
 ><mfrac
 ><mn>1</mn><msqrt><mn>2</mn></msqrt></mfrac
 ><annotation encoding="TeX">\frac{1}{\sqrt{2}}</annotation></semantics
 ></math
 >
    </p>

    <p>
      One over square root of two (display style):
      <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"
 ><semantics
 ><mfrac
 ><mn>1</mn><msqrt><mn>2</mn></msqrt></mfrac
 ><annotation encoding="TeX">\frac{1}{\sqrt{2}}</annotation></semantics
 ></math
 >
    </p>
  </body>
</html>
```

还有更复杂的工具可以将任意的 Latex 文档转换为 MathML 形式的文档。例如，使用 LaTeXML 可以将 `foo.tex` 转换为 HTML 或 EPUB 文档：

```bash
latexmlc --dest foo.html foo.tex # Generate a HTML document foo.html
latexmlc --dest foo.epub foo.tex # Generate an EPUB document foo.epub
```

`latexmlc` 接受一个 `--javascript` 参数，你可以使用这个参数来包含上面提到的任意一个回退脚本：

```bash
latexmlc --dest foo.html --javascript=https://fred-wang.github.io/mathml.css/mspace.js foo.tex  # Add the CSS fallback
latexmlc --dest foo.html --javascript=https://fred-wang.github.io/mathjax.js/mpadded-min.js foo.tex # Add the MathJax fallback
```

**备注：** 命令行工具可以在服务端使用，例如：MediaWiki 使用 Mathoid 以完成从 LaTeX 到 MathML 的转换。

图形界面
----

在本节中，我们将回顾一些提供图形界面的编辑工具。

### 输入框

在数学公式输入框中集成简单语法转换器是一种较为简单的方法。例如，Thunderbird 和 SeaMonkey 提供了 **Insert > Math** 的命令，这一命令会弹出一个窗口，其中包含了一个从 LaTeX 到 MathML 的输入字段和 MathML 的实时预览：

![Thunderbird 的 LaTeX 输入框](/zh-CN/docs/Web/MathML/Authoring/thunderbird.png)

**备注：** 你也可以使用 **Insert > HTML** 命令直接插入 MathML 内容。

LibreOffice 的公式编辑器（文件 → 新建 → 公式）提供了增强功能：它的 *StartMath* 语法输入框提供了额外的公式面板来插入预定义的数学公式结构。

![Libre Office 中的 StarMath 输入框](/zh-CN/docs/Web/MathML/Authoring/libreoffice.png)

**备注：** 要获取 libreoffice 的 MathML 代码，请将文档保存为 `mml` 格式，并在你喜欢的文本编辑器中打开它。

### 所见即所得编辑器

其他的编辑器直接将编辑数学公式的功能集成到其所见即所得界面。以下截图来自 LyX 和 TeXmacs，它们都支持导出 HTML：

![Lyx 的示例](/zh-CN/docs/Web/MathML/Authoring/lyx.png)

![TeXmacs 的示例](/zh-CN/docs/Web/MathML/Authoring/texmacs.png)

**备注：** 默认情况下，Lyx 和 TeXmacs 会在它们的 HTML 输出中使用数学公式的图像。要使用 MathML，对于前者，请参照这里的说明；对于后者，请选择 `User preference > Convert > Export mathematical formulas as MathML`。

### 光学字符和手写识别

最后一种输入数学公式的方法是使用光学字符识别或手写识别的用户界面。其中的部分工具支持数学公式，并支持导出 MathML。以下截图来自 MyScript 的演示。

![MyScript](/zh-CN/docs/Web/MathML/Authoring/myscript.png)


MathML 元素参考 - MathML

MathML 元素参考
===========

这是一份按字母排序的 MathML **呈现型**元素列表。

**呈现型标记**（**presentation markup**）相关条目被用来描述数学记号的布局结构，而**内容型标记**（**content markup**）则用于提供潜在的数学含义，MathML 解析器不支持渲染内容型标记（见 Firefox bug 276028）。若想了解更多关于内容型标记的信息，可以考虑阅读 MathML 3 规范的第四章。

MathML 元素实现了 `MathMLElement` 类。

MathML 呈现型元素（字母排序）
------------------

### math

* `<math>`（顶层元素）
### A

* `<maction>`（将动作绑定到子表达式）
* `<maligngroup>`（对齐分组）
* `<malignmark>`（对齐点）
### E

* `<menclose> (en-US)`（被包裹的内容）
* `<merror> (en-US)`（被包裹的语法错误消息）
### F

* `<mfenced> (en-US)`（圆括号）
已弃用
* `<mfrac> (en-US)`（因子 Fraction）
### G

* `<mglyph>`（显示非标准符号）
### I

* `<mi> (en-US)`（标识符 Identifier）
### L

* `<mlabeledtr>`（表格或矩阵中，带标记的行）
* `<mlongdiv>`（长除法记号）
### M

* `<mmultiscripts> (en-US)`（Prescript 和张量指标 tensor indice）
### N

* `<mn> (en-US)`（数字）
### O

* `<mo> (en-US)`（运算符 Operator）
* `<mover> (en-US)`（上标）
### P

* `<mpadded> (en-US)`（在内容周围增设空白）
* `<mphantom> (en-US)`（保留空白占位的不可见内容）
### R

* `<mroot>`（带指定根数的根号）
* `<mrow>`（分组后的子表达式）
### S

* `<ms> (en-US)`（字符串字面量）
* `<mscarries>`（附注 Annotation，比如进位）
* `<mscarry>`（单进位， `<mscarries>` 的子元素）
* `<msgroup>`（`<mstack>` 和 `<mlongdiv>` 元素内的行组）
* `<msline>`（在 `<mstack>` 元素内的水平行）
* `<mspace>`（空白）
* `<msqrt>`（不带根数的平方根）
* `<msrow>`（在 `<mstack>` 元素中的行）
* `<mstack>`（堆叠式对齐）
* `<mstyle> (en-US)`（改变样式）
* `<msub>`（下角标）
* `<msup>`（上角标）
* `<msubsup>`（上下角标对）
### T

* `<mtable> (en-US)`（表格或矩阵）
* `<mtd> (en-US)`（表格或矩阵中的单元格）
* `<mtext> (en-US)`（文本）
* `<mtr> (en-US)`（表格或矩阵中的行）
### U

* `<munder> (en-US)`（下标）
* `<munderover> (en-US)`（上标 - 下标对）
### 其他元素

* `<semantics> (en-US)`（语义附注的容器）
* `<annotation>` (en-US)（数据附注）
* `<annotation-xml>` (en-US)（XML 附注）
MathML 呈现型元素（类别分类）
------------------

### 顶层元素

* `<math>`
### 字符/符号元素

* `<mglyph>`
* `<mi> (en-US)`
* `<mn> (en-US)`
* `<mo> (en-US)`
* `<ms> (en-US)`
* `<mspace>`
* `<mtext> (en-US)`
### 通用布局元素

* `<menclose> (en-US)`
* `<merror> (en-US)`
* `<mfenced> (en-US)`
已弃用
* `<mfrac> (en-US)`
* `<mpadded> (en-US)`
* `<mphantom> (en-US)`
* `<mroot>`
* `<mrow>`
* `<msqrt>`
* `<mstyle> (en-US)`
### 边标和角标元素

* `<mmultiscripts> (en-US)`
* `<mover> (en-US)`
* `<mprescripts> (en-US)`
* `<msub>`
* `<msubsup>`
* `<msup>`
* `<munder> (en-US)`
* `<munderover> (en-US)`
* `<none> (en-US)`
### 表格数学

* `<maligngroup>`
* `<malignmark>`
* `<mlabeledtr>`
* `<mtable> (en-US)`
* `<mtd> (en-US)`
* `<mtr> (en-US)`
### 初等数学

* `<mlongdiv>`
* `<mscarries>`
* `<mscarry>`
* `<msgroup>`
* `<msline>`
* `<msrow>`
* `<mstack>`
### 尚无分类的元素

* `<maction>`
语义附注元素
------

* `<annotation>` (en-US)
* `<annotation-xml>` (en-US)
* `<semantics> (en-US)`
请参阅
---

* MathML
* MathML 属性参考


举个例子 - MathML

举个例子
====

你可以在下面找到一些可以参考的例子，以帮助你了解如何使用 MathML 在 Web 内容中显示越来越复杂的数学概念。

勾股定理

展示一个勾股定理的证明的小例子。

推导二次方程式

简述二次方程式的推导过程。

MathML 极限测试

渲染大量数据的测试。


属性 - MathML

属性
==

此页面是 MathML 属性的字母表。要了解每个属性的更多详细信息，请参见 MathML 元素页面和全局属性页面 (en-US)。值 (en-US)页面也介绍了有关 MathML 属性常用值的一些说明。

**备注：** 就像 MathML 主页所解释的那样，MDN 使用 MathML 核心作为参考规范。不过，一些浏览器仍在使用的遗留特性也被记录在案。你可以在 MathML 4 中找到有关这些特性和其他特性的更多详细信息。

| 名称 | 接受该属性的元素 | 描述 |
| --- | --- | --- |
| `accent` | `<mo> (en-US)` | 一个 `<boolean>` (en-US) 值，表示在作为下标或上标使用时，运算符是否应着重表示。 |
| `accent` | `<mover> (en-US)`、`<munderover> (en-US)` | 一个 `<boolean>` (en-US) 值，表示下标是否应着重表示。 |
| `accentunder` | `<munder> (en-US)`、`<munderover> (en-US)` | 一个 `<boolean>` (en-US) 值，表示上标是否应着重表示。 |
| `actiontype`
已弃用
 | `<maction>` | 一个字符串值，用于指定此元素发生的操作。 |
| `align` | `<mtable> (en-US)` | 指定表格相对于环境的垂直对齐方式。 |
| `background`
已弃用
 | `<mstyle> (en-US)` | 请使用 CSS `background-color` 代替。 |
| `close`
已弃用
 | `<mfenced> (en-US)` | 用于结尾分隔符的字符串。 |
| `color`
已弃用
 | `<mstyle> (en-US)` | 请使用 CSS `color` 代替。 |
| `columnalign` | `<mtable> (en-US)`、`<mtd> (en-US)`、`<mtr> (en-US)` | 指定表格单元格的水平对齐方式。 |
| `columnlines` | `<mtable> (en-US)` | 指定表格列边框。 |
| `columnspacing` | `<mtable> (en-US)` | 指定表格列间距。 |
| `columnspan` | `<mtd> (en-US)` | 一个非负整数值，表示单元格扩展到多少表格列。 |
| `denomalign`
已弃用
 | `<mfrac> (en-US)` | 分数下分母的对齐方式。 |
| `depth` | `<mpadded> (en-US)` | 一个 `<length-percentage>` 值，表示所需的深度（基线以下）。 |
| `dir` | 所有 MathML 元素 (en-US) | 文本方向，可能的值为 `ltr`（从左到右）或 `rtl`（从右到左）。 |
| `display` | `<math>` | 指定渲染模式，允许的值为 `block` 和 `inline`。 |
| `displaystyle` | 所有 MathML 元素 (en-US) | 一个 `<boolean>` (en-US) 值，指定是否将 math-style (en-US) 设置为 `normal`（如果为真）或 `compact`（其他情况下）。 |
| `fence` | `<mo> (en-US)` | 一个 `<boolean>` (en-US) 值，指定运算符是否为分隔符（如括号）。该属性没有视觉效果。 |
| `fontfamily`
已弃用
 | `<mstyle> (en-US)` | 请使用 CSS `font-family` 代替。 |
| `fontsize`
已弃用
 | `<mstyle> (en-US)` | 请使用 CSS `font-size` 代替。 |
| `fontstyle`
已弃用
 | `<mstyle> (en-US)` | 请使用 CSS `font-style` 代替。 |
| `fontweight`
已弃用
 | `<mstyle> (en-US)` | 请使用 CSS `font-weight` 代替。 |
| `frame` | `<mtable> (en-US)` | 指定整个 `<mtable> (en-US)` 的边框显示。可能的值为 `none`（默认）、`solid` 和 `dashed`。 |
| `framespacing` | `<mtable> (en-US)` | 指定在表格和 `frame` 之间添加的额外空间。 |
| `height` | `<mpadded> (en-US)`、`<mspace>` | 一个 `<length-percentage>` 值，表示所需的高度（基线之上）。 |
| `href` | 所有 MathML 元素 (en-US) | 用于设置指向指定 URI 的超链接。 |
| `id` | 所有 MathML 元素 (en-US) | 设置与元素相关的唯一标识符。 |
| `linethickness` | `<mfrac> (en-US)` | 一个 `<length-percentage>` 值，表示水平分数线的厚度。 |
| `lspace` | `<mo> (en-US)` | 一个 `<length-percentage>` 值，表示运算符前的空间大小。 |
| `lspace` | `<mpadded> (en-US)` | 一个 `<length-percentage>` 值，表示子内容的定位点相对于元素定位点的水平位置。 |
| `lquote`
已弃用
 | `<ms> (en-US)` | 包含内容的起始引号，默认值为 `"`。 |
| `mathbackground` | 所有 MathML 元素 (en-US) | 元素的 background-color 值。 |
| `mathcolor` | 所有 MathML 元素 (en-US) | 元素的 color 值。 |
| `mathsize` | 所有 MathML 元素 (en-US) | 一个 `<length-percentage>` 值，作为元素的 `font-size` 值。 |
| `mathvariant` | 所有 MathML 元素 (en-US) | 标记元素的逻辑类别，在排版上有所不同。 |
| `maxsize` | `<mo> (en-US)` | 一个 `<length-percentage>` 值，表示运算符在拉伸状态下的最大尺寸。 |
| `minsize` | `<mo> (en-US)` | 一个 `<length-percentage>` 值，表示运算符在拉伸状态下的最小尺寸。 |
| `movablelimits` | `<mo> (en-US)` | 一个 `<boolean>` (en-US) 值，表示当 math-style (en-US) 设置为 `compact` 时，所附的下标和上标是否移动到下标和上标位置。 |
| `notation` | `<menclose> (en-US)` | 应用于子元素的符号列表，以空白符分隔。 |
| `numalign`
已弃用
 | `<mfrac> (en-US)` | 分数中分子的对齐方式。 |
| `open`
已弃用
 | `<mfenced> (en-US)` | 用于起始分隔符的字符串。 |
| `rowalign` | `<mtable> (en-US)`、`<mtd> (en-US)`、`<mtr> (en-US)` | 指定单元格的垂直对齐方式。 |
| `rowlines` | `<mtable> (en-US)` | 指定表格行的边框大小。 |
| `rowspacing` | `<mtable> (en-US)` | 指定表格行间距。 |
| `rowspan` | `<mtd> (en-US)` | 一个非负整数值，表示单元格扩展到多少行。 |
| `rspace` | `<mo> (en-US)` | 一个 `<length-percentage>` 值，表示运算符后的空格大小。 |
| `rquote`
已弃用
 | `<ms> (en-US)` | 包含内容的结尾引号，默认值为 `"`。 |
| `scriptlevel` | 所有 MathML 元素 (en-US) | 指定了元素的 math-depth (en-US) 值。参见 scriptlevel 页面 (en-US)以了解接受的值和映射。 |
| `scriptminsize`
已弃用
 | `<mstyle> (en-US)` | 指定由于 `scriptlevel` 的更改而允许的最小字体大小。 |
| `scriptsizemultiplier`
已弃用
 | `<mstyle> (en-US)` | 指定倍数，用于根据 `scriptlevel` 的变化调整字体大小。 |
| `selection`
已弃用
 | `<maction>` | 子元素可见，仅在某些 `actiontype` 值中被考虑。 |
| `separator` | `<mo> (en-US)` | 一个 `<boolean>` (en-US) 值，指定了该运算符是否为分割符（如逗号）。这个属性没有视觉效果。 |
| `separators`
已弃用
 | `<mfenced> (en-US)` | 用于不同分隔符的零个或多个字符的序列。 |
| `stretchy` | `<mo> (en-US)` | 一个 `<boolean>` (en-US) 值，表示运算符是否拉伸到相邻元素的大小。 |
| `subscriptshift`
已弃用
 | `<msub>`、`<msubsup>`、`<mmultiscripts> (en-US)` | 一个 `<boolean>` (en-US) 值，表示下标基线下移的最小量。 |
| `superscriptshift`
已弃用
 | `<msup>`、`<msubsup>`、`<mmultiscripts> (en-US)` | 一个 `<length-percentage>` 值，表示上标基线上移的最小量。 |
| `symmetric` | `<mo> (en-US)` | 一个 `<boolean>` (en-US) 值，表示拉伸运算符是否应围绕数学虚轴（居中分数线）垂直对称。 |
| `voffset` | `<mpadded> (en-US)` | 一个 `<length-percentage>` 值，表示子内容的定位点相对于元素定位点的垂直位置。 |
| `width` | `<mpadded> (en-US)`、`<mspace>`、`<mtable> (en-US)` | 一个 `<length-percentage>` 值，表示所需的宽度。 |
| `xmlns` | `<math>` | 指定 MathML 命名空间的 URI（`http://www.w3.org/1998/Math/MathML`） |


<mroot> - MathML

<mroot>
=======

MathML **`<mroot>`** 元素用来表示一个有明确根指数的根式。它接受两个参数，语法如下：`<mroot> base index </mroot>`。

属性
--

该元素接受全局 MathML 属性 (en-US)。

示例
--

```html
<math display="block">
  <mroot>
    <mi>x</mi>
    <mn>3</mn>
  </mroot>
</math>
```

规范
--

| Specification |
| --- |
| MathML Core # radicals-msqrt-mroot |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `<msqrt>`（不带根指数的平方根）


<math> - MathML

<math>
======

**`<math>`** MathML 元素是顶级的 MathML 元素，用于编写单个数学公式。可以将其放在允许流式内容的 HTML 内容中。

**备注：** 参阅编写 MathML 页面以了解如何正确地在网页中集成 MathML 公式，有关更多的演示，请参阅示例页面。

属性
--

该元素的属性包括全局 MathML 属性 (en-US)和以下属性：

`display`

该枚举 (en-US)属性指定了应如何渲染封闭的 MathML 标记。其可以是以下值之一：

* `block`，这意味着该元素将显示在当前文本范围之外的块中，并将 `math-style` (en-US) 设置为 `normal`。
* `inline`，这意味着该元素将显示在当前的文本范围内，并将 `math-style` (en-US) 设置为 `compact`。

如果没有指定该属性，其默认值为 `inline`。

示例
--

该示例包含两个 MathML 公式。第一个在其自己的居中的块中渲染，根据需要占用足够的空间。第二个公式则在其文本段落中渲染，缩小其尺寸和间距以最小化其高度。

```html
<p>
  无穷级数
  <math display="block">
    <mrow>
      <munderover>
        <mo>∑</mo>
        <mrow>
          <mi>n</mi>
          <mo>=</mo>
          <mn>1</mn>
        </mrow>
        <mrow>
          <mo>+</mo>
          <mn>∞</mn>
        </mrow>
      </munderover>
      <mfrac>
        <mn>1</mn>
        <msup>
          <mi>n</mi>
          <mn>2</mn>
        </msup>
      </mfrac>
    </mrow>
  </math>
  的和等于实数
  <math display="inline">
    <mfrac>
      <msup>
        <mi>π</mi>
        <mn>2</mn>
      </msup>
      <mn>6</mn>
    </mfrac></math
 >。
</p>
```

规范
--

| Specification |
| --- |
| MathML Core # the-top-level-math-element |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* HTML 顶级元素：`<html>`
* SVG 顶级元素：`<svg>`


<maction> - MathML

<maction>
=========

**已弃用:** 不再推荐使用该特性。虽然一些浏览器仍然支持它，但也许已从相关的 web 标准中移除，也许正准备移除或出于兼容性而保留。请尽量不要使用该特性，并更新现有的代码；参见本页面底部的兼容性表格以指导你作出决定。请注意，该特性随时可能无法正常工作。

**`<maction>`** MathML 元素允许将行为绑定到数学表达式上。默认情况下，只有第一个子元素会被渲染，但是一些浏览器可能会根据 `actiontype` 和 `selection` 属性来实现自定义行为。

**备注：** 从历史的角度来看，该元素提供了一种使 MathML 公式可以交互的机制。但如今，建议使用 JavaScript 和其他 Web 技术来实现这种用例。

属性
--

该元素的属性包括全局 MathML 属性 (en-US)以及以下属性：

`actiontype`
已弃用

非标准

指定该元素发生的行为。某些浏览器会根据以下值实现特殊行为：

* `statusline`：如果*表达式*被点击或者读者将指针移至其上，将会把*消息*（message）发送到浏览器的状态栏。语法如下：`<maction actiontype="statusline"> expression message </maction>`。
* `toggle`：当子表达式被点击时，选中的子表达式会交替显示。因此，每次单击都会增加 `selection` 的值。语法如下：`<maction actiontype="toggle" selection="positive-integer" > expression1 expression2 expressionN </maction>`。

`selection`
已弃用

非标准

当前可见的子元素，仅适用于 `actiontype="toggle"` 或非标准的 `actiontype` 值。默认值为 `1`，即第一个子元素。

示例
--

以下示例演示了如何使用“toggle”这个 `actiontype`：

```html
<p>
  尝试多次点击这个公式：

  <math display="block">
    <maction actiontype="toggle">
      <mfrac>
        <mn>6</mn>
        <mn>8</mn>
      </mfrac>

      <mfrac>
        <mrow>
          <mn>3</mn>
          <mo>×</mo>
          <mn>2</mn>
        </mrow>
        <mrow>
          <mn>4</mn>
          <mo>×</mo>
          <mn>2</mn>
        </mrow>
      </mfrac>

      <mfrac>
        <mn>3</mn>
        <mn>4</mn>
      </mfrac>
    </maction>
  </math>
</p>
```

规范
--

| Specification |
| --- |
| MathML Core # dfn-maction |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


<msub> - MathML

<msub>
======

MathML **`<msub>`** 元素用于为表达式附加下标。

使用语法如下：`<msub> base subscript </msub>`。

属性
--

该元素的属性包括全局 MathML 属性 (en-US)和以下已弃用的属性：

`subscriptshift`
已弃用

非标准

`<length-percentage>` 值，表示下标基线向下移动的最小距离。

**备注：** 对于 `subscriptshift` 属性，一些浏览器可能也会接受旧版 MathML 长度 (en-US)。

示例
--

```html
<math display="block">
  <msub>
    <mi>X</mi>
    <mn>1</mn>
  </msub>
</math>
```

规范
--

| Specification |
| --- |
| MathML Core # subscripts-and-superscripts-msub-msup-msubsup |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `<msup>`（上标）
* `<msubsup>`（上下标）
* `<mmultiscripts> (en-US)`（四角标，张量式标记）


<msqrt> - MathML

<msqrt>
=======

MathML **`<msqrt>`** 元素用于表示平方根（不显示根指数）。它只接受一个参数，语法如下：`<msqrt> base </msqrt>`。

属性
--

该元素接受全局 MathML 属性 (en-US)。

示例
--

```html
<math display="block">
  <msqrt>
    <mi>x</mi>
  </msqrt>
</math>
```

规范
--

| Specification |
| --- |
| MathML Core # radicals-msqrt-mroot |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `<mroot>`（带有根指数的方根）


<mspace> - MathML

<mspace>
========

**`<mspace>`** MathML 元素用来显示一段空白，空白的大小由它自身的属性设置。

属性
--

该元素的属性包括全局 MathML 属性 (en-US)以及下列属性：

`depth`

`<length-percentage>` 值，表示空白（在基线下方）的深度。

`height`

`<length-percentage>` 值，表示空白（在基线上方）的高度。

`width`

`<length-percentage>` 值，表示空白的宽度。

**备注：** 对于 `depth`、`height`、`width` 属性，一些浏览器可能也接受旧版 MathML 长度值 (en-US)。

示例
--

```html
<math display="block">
  <mn>1</mn>
  <mspace depth="40px" height="20px" width="100px"
 style="background: lightblue;"/>
  <mn>2</mn>
</math>
```

规范
--

| Specification |
| --- |
| MathML Core # space-mspace |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `<mpadded> (en-US)`
* `<mphantom> (en-US)`


<msubsup> - MathML

<msubsup>
=========

MathML `<msubsup>` 元素用于为表达式同时附加上标和下标。

使用语法如下：`<msubsup> base subscript superscript </msubsup>`。

属性
--

该元素的属性包括全局 MathML 属性 (en-US)和以下已弃用的属性：

`subscriptshift`
已弃用

非标准

`<length-percentage>` 值，表示下标基线向下移动的最小距离。

`superscriptshift`
已弃用

非标准

`<length-percentage>` 值，表示上标基线向上移动的最小距离。

**备注：** 对于 `subscriptshift` 和 `superscriptshift` 属性，一些浏览器可能也会接受旧版 MathML 长度 (en-US)。

示例
--

```html
<math display="block">
  <msubsup>
    <mo>∫<!-- 积分符号 --></mo>
    <mn>0</mn>
    <mn>1</mn>
  </msubsup>
</math>
```

规范
--

| Specification |
| --- |
| MathML Core # subscripts-and-superscripts-msub-msup-msubsup |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `<msub>`（上标）
* `<msup>`（下标）
* `<mmultiscripts> (en-US)`（四角标，张量式标记）


<mrow> - MathML

<mrow>
======

MathML `<mrow>` 元素用于对连续多行表达式的不同子表达式进行分组，一条子表达式通常算作一行，至少包含一或多个操作符 (en-US)与其运算对象（比如 `<mi> (en-US)` 和 `<mn> (en-US)`）。此元素呈现为包含其内容的水平行。

在编写 MathML 表达式时，你应该使用 `<mrow>` 将表达式中的元素分组，就像它们在数学解释时的分成一行行一样。正确的分组有助于表达式的呈现，具体体现在以下几个方面：

* 如果有需要，它会改变间距来改善显示效果。
* 它允许采用更明智的断行和缩进算法。
* 通过自动化系统，如计算机代数系统和音频渲染器（automated systems such as computer algebra systems and audio renderers），它能简化表达式的解释（interpretation）过程。
属性
--

class, id, style

用来供样式表使用。

dir

行内公式的书写方向。可能的值为 `ltr`（自左向右）或 `rtl`（自右向左）。

href

用于设置一个指向指定的 URI 的超链接。

mathbackground

背景色。支持 `#rgb`、`#rrggbb` 和 HTML 颜色 (en-US)。

mathcolor

文本颜色。支持 `#rgb`、`#rrggbb` 和 HTML 颜色 (en-US)。

示例
--

```html
<math>
  <mrow>
    <mn> 1 </mn>
    <mo> + </mo>
    <mn> 1 </mn>
  </mrow>

  <mrow>
    <mo> ( </mo>
    <mrow>
      <mi> x </mi>
      <mo> , </mo>
      <mi> y </mi>
    </mrow>
    <mo> ) </mo>
  </mrow>
</math>
```

规范
--

| Specification |
| --- |
| MathML Core # horizontally-group-sub-expressions-mrow |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* HTML 分组元素：`<div>`


<msup> - MathML

<msup>
======

MathML **`<msup>`** 元素用于为表达式附加上标。

使用语法如下：`<msup> base superscript </msup>`。

属性
--

该元素的属性包括全局 MathML 属性 (en-US)和以下已弃用的属性：

`superscriptshift`
已弃用

非标准

`<length-percentage>` 值，表示上标基线向上移动的最小距离。

**备注：** 对于 `superscriptshift` 属性，一些浏览器可能也会接受旧版 MathML 长度 (en-US)。

示例
--

```html
<math display="block">
  <msup>
    <mi>X</mi>
    <mn>2</mn>
  </msup>
</math>
```

规范
--

| Specification |
| --- |
| MathML Core # subscripts-and-superscripts-msub-msup-msubsup |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `<msub>`（下标）
* `<msubsup>`（上下标）
* `<mmultiscripts> (en-US)`（四角标，张量式标记）


证明毕达哥拉斯定理 - MathML

证明毕达哥拉斯定理
=========

现在，我们来证明毕达哥拉斯定理（勾股定理）：

**命题**：在一个直角三角形中，斜边的平方等于其他两边的平方之和。

例如，设 a 和 b 为两直角边，c 为斜边，那么

a
2

+

b
2

=

c
2

。

**证明：** 我们可以通过代数证明来展示大正方形面积等于内正方形（斜边的平方）加上四个三角形的面积：

(
a
+
b
)

2

=

c
2

+
4
⋅
(

1
2

a
b
)

a
2

+
2
a
b
+

b
2

=

c
2

+
2
a
b

a
2

+

b
2

=

c
2


推导二次方程求根公式 - MathML

推导二次方程求根公式
==========

本页概述了二次方程求根公式的推导过程。

我们取一般形式的二次方程，并解出 x：

a

x
2

+
b

x

+
c

=

0

a

x
2

+
b

x

=

−
c

x
2

+

b
a

x

=

−
c

a

两边同时除以二次项系数

x
2

+

b

a

x
+

(

b

2
a

)

2

=

−
c
(
4
a
)

a
(
4
a
)

+

b
2

4

a
2

完成配方

(
x
+

b

2
a

)
(
x
+

b

2
a

)

=

b
2

−
4
a
c

4

a
2

推导出判别式

(
x
+

b

2
a

)

2

=

b
2

−
4
a
c

4

a
2

x
+

b

2
a

=

b
2

−
4
a
c

4

a
2

x

=

−
b

2
a

±

{
C
}

b
2

−
4
a
c

4

a
2

这就是顶点公式

x

=

−
b
±

{
C
}

b
2

−
4
a
c

2
a