交流网站建设项目背景,图片在线制作编辑,大气网站欣赏,中山网站建设咨询第二十一章#xff1a;数学 原文#xff1a;21. Math 译者#xff1a;飞龙 协议#xff1a;CC BY-NC-SA 4.0 Math对象用作多个数学函数的命名空间。本章提供了一个概述。
数学属性
Math的属性如下#xff1a;
Math.E
欧拉常数#xff08;e#xff09;
Math.LN2
2 …第二十一章数学 原文21. Math 译者飞龙 协议CC BY-NC-SA 4.0 Math对象用作多个数学函数的命名空间。本章提供了一个概述。
数学属性
Math的属性如下
Math.E
欧拉常数e
Math.LN2
2 的自然对数
Math.LN10
10 的自然对数
Math.LOG2E
e 的底数 2 对数
Math.LOG10E
e 的十进制对数
Math.PI
圆的周长与直径的比值3.14159 …π
Math.SQRT1_2
一半的平方根
Math.SQRT2
二的平方根
数值函数
Math的数值函数包括以下内容
Math.abs(x)
返回x的绝对值。
Math.ceil(x)
返回大于等于x的最小整数 Math.ceil(3.999)
4Math.ceil(3.001)
4Math.ceil(-3.001)
-3Math.ceil(3.000)
3有关将浮点数转换为整数的更多信息请参阅转换为整数。
Math.exp(x)
返回 e^x其中 e 是欧拉常数Math.E。这是Math.log()的反函数。
Math.floor(x)
返回小于等于x的最大整数 Math.floor(3.999)
3Math.floor(3.001)
3Math.floor(-3.001)
-4Math.floor(3.000)
3有关将浮点数转换为整数的更多信息请参阅转换为整数。
Math.log(x)
返回x的自然以 e 为底对数 ln(x)。这是Math.exp()的反函数。
Math.pow(x, y)
返回 x^yx的y次幂 Math.pow(9, 2)
81Math.pow(36, 0.5)
6Math.round(x)
返回x四舍五入到最接近的整数如果在两个整数之间则为较大的整数 Math.round(3.999)
4Math.round(3.001)
3Math.round(3.5)
4Math.round(-3.5)
-3有关将浮点数转换为整数的更多信息请参阅转换为整数。
Math.sqrt(x)
返回x的平方根 Math.sqrt(256)
16三角函数
三角函数方法接受弧度作为角度并返回。以下函数向您展示了如何实现转换如果需要的话 从度到弧度 function toRadians(degrees) {return degrees / 180 * Math.PI;
}以下是交互 toRadians(180)3.141592653589793 toRadians(90)1.5707963267948966 从弧度到度jsfunction toDegrees(radians) {return radians / Math.PI * 180;}以下是交互js toDegrees(Math.PI * 2)360 toDegrees(Math.PI)180三角函数方法如下Math.acos(x)返回x的反余弦值。Math.asin(x)返回x的反正弦值。Math.atan(x)返回x的反正切值。Math.atan2(y, x)返回商的反正切值。Math.cos(x)返回x的余弦值。Math.sin(x)返回x的正弦值。Math.tan(x)返回x的正切值。## 其他函数以下是剩余的Math函数min(x1?, x2?, ...)返回参数中的最小数jsMath.min()
InfinityMath.min(27)
27Math.min(27, -38)
-38Math.min(27, -38, -43)
-43通过apply()在数组上使用它参见func.apply(thisValue, argArray) Math.min.apply(null, [27, -38, -43])
-43max(x1?, x2?, ...)
返回参数中的最大数 Math.max()
-InfinityMath.max(7)
7Math.max(7, 10)
10Math.max(7, 10, -333)
10通过apply()在数组上使用它参见func.apply(thisValue, argArray) Math.max.apply(null, [7, 10, -333])
10Math.random()
/*** Compute a random integer within the given range.** param [lower] Optional lower bound. Default: zero.* returns A random integer i, lower ≤ i upper*/
function getRandomInteger(lower, upper) {if (arguments.length 1) {upper lower;lower 0;}return Math.floor(Math.random() * (upper - lower)) lower;
}第二十二章JSON 原文22. JSON 译者飞龙 协议CC BY-NC-SA 4.0 JSONJavaScript 对象表示是一种用于数据存储的纯文本格式。它已经成为 Web 服务、配置文件等数据交换格式的一种流行选择。ECMAScript 5 有一个 API用于将 JSON 格式的字符串转换为 JavaScript 值解析以及反之字符串化。
背景
本节解释了 JSON 是什么以及它是如何创建的。
数据格式
JSON 将数据存储为纯文本。它的语法是 JavaScript 表达式语法的子集。例如
{first: Jane,last: Porter,married: true,born: 1890,friends: [ Tarzan, Cheeta ]
}JSON 使用 JavaScript 表达式中的以下结构:
复合
JSON 数据的对象和 JSON 数据的数组
原子
字符串、数字、布尔值和空值
它遵循以下规则 字符串必须始终用双引号括起来例如像mystr这样的字符串字面量是非法的。 属性键必须用双引号括起来
历史
Douglas Crockford 于 2001 年发现了 JSON。他给它起了个名字并在json.org上发布了一个规范 我发现了 JSON。我不主张发明 JSON因为它已经存在于自然界中。我所做的是发现它我给它起了名字我描述了它的有用之处。我不主张自己是第一个发现它的人我知道至少有其他人在我之前至少一年发现了它。我发现的最早的情况是Netscape 有人在至少 1996 年就开始使用 JavaScript 数组文字进行数据通信而这至少比我想到这个想法早了五年。 最初Crockford 希望 JSON 有一个名字叫JavaScript 标记语言但是 JSML 的首字母缩写已经被JSpeech 标记语言使用了。
JSON 规范已经被翻译成许多人类语言现在有许多编程语言的库支持解析和生成 JSON。
语法
Douglas Crockford 创建了一张 JSON 名片正面有一个徽标参见图 22-1背面有完整的语法参见图 22-2。这使得 JSON 的简单性在视觉上显而易见。
图 22-1JSON 名片的正面显示了一个徽标来源Eric Miraglia。
图 22-2JSON 名片的背面包含完整的语法来源Eric Miraglia。
语法可以转录如下:
object{ }{ members }memberspairpair , memberspairstring : valuearray[ ][ elements ]elementsvaluevalue , elementsvaluestringnumberobjectarraytruefalsenullstring chars charscharchar charscharany-Unicode-character-except--or-\-or-control-character\ \\ \/ \b \f \n \r \t\u four-hex-digitsnumberintint fracint expint frac expintdigitdigit1-9 digits- digit- digit1-9 digitsfrac. digitsexpe digitsdigitsdigitdigit digitsee e e-E E E-全局变量JSON用作生成和解析带有 JSON 数据的字符串的函数的命名空间。
JSON.stringify(value, replacer?, space?)
JSON.stringify(value, replacer?, space?)将 JavaScript 值value转换为 JSON 格式的字符串。它有两个可选参数。
可选参数replacer用于在对其进行字符串化之前更改value。它可以是 一个节点访问者参见通过节点访问者转换数据在将其字符串化之前转换值树。例如 function replacer(key, value) {if (typeof value number) {value 2 * value;}return value;
}使用 replacer JSON.stringify({ a: 5, b: [ 2, 8 ] }, replacer){a:10,b:[4,16]} 隐藏所有不在列表中的属性键非数组对象的属性的属性白名单。例如js JSON.stringify({foo: 1, bar: {foo: 1, bar: 1}}, [bar]){bar:{bar:1}}白名单对数组没有影响js JSON.stringify([a, b], [0])[a,b]可选参数space影响输出的格式。如果没有这个参数stringify的结果将是单行文本jsconsole.log(JSON.stringify({a: 0, b: [\n]}))
{a:0,b:[\n]}使用它可以插入换行符并且通过数组和对象的每个嵌套级别增加缩进。有两种指定缩进方式的方法
一个数字
将数字乘以缩进级别并将行缩进为相同数量的空格。小于 0 的数字被解释为 0大于 10 的数字被解释为 10 console.log(JSON.stringify({a: 0, b: [\n]}, null, 2))
{a: 0,b: [\n]
}一个字符串
要缩进重复给定的字符串以表示每个缩进级别。只使用字符串的前 10 个字符 console.log(JSON.stringify({a: 0, b: [\n]}, null, |--))
{
|--a: 0,
|--b: [
|--|--\n
|--]
}因此以下对JSON.stringify()的调用会将对象打印为一个格式良好的树
JSON.stringify(data, null, 4)JSON.stringify()忽略的数据
在对象中JSON.stringify()只考虑可枚举的自有属性参见属性特性和属性描述符。以下示例演示了忽略了不可枚举的自有属性obj.foo var obj Object.defineProperty({}, foo, { enumerable: false, value: 7 });Object.getOwnPropertyNames(obj)
[ foo ]obj.foo
7JSON.stringify(obj)
{}JSON.stringify()处理不受 JSON 支持的值例如函数和undefined的方式取决于它们遇到的位置。不支持的值本身导致stringify()返回undefined而不是字符串 JSON.stringify(function () {})
undefined其值不受支持的属性将被简单地忽略 JSON.stringify({ foo: function () {} })
{}数组中不支持的值将被字符串化为null JSON.stringify([ function () {} ])
[null]toJSON()方法
如果JSON.stringify()遇到具有toJSON方法的对象则使用该方法获取要字符串化的值。例如 JSON.stringify({ toJSON: function () { return Cool } })
Cool日期已经有一个产生 ISO 8601 日期字符串的toJSON方法 JSON.stringify(new Date(2011-07-29))
2011-07-28T22:00:00.000ZtoJSON方法的完整签名如下
function (key)key参数允许您根据上下文以不同方式进行字符串化。它始终是一个字符串并指示在父对象中找到您的对象的位置
根位置
空字符串
属性值
属性键
数组元素
元素的索引作为字符串
我将通过以下对象演示toJSON()
var obj {toJSON: function (key) {// Use JSON.stringify for nicer-looking outputconsole.log(JSON.stringify(key));return 0;}
};如果使用JSON.stringify()则每次出现obj都会被替换为0。通知toJSON()方法在属性键foo和数组索引 0 处遇到了obj JSON.stringify({ foo: obj, bar: [ obj ]})
foo
0
{foo:0,bar:[0]}内置的toJSON()方法如下 Boolean.prototype.toJSON() Number.prototype.toJSON() String.prototype.toJSON() Date.prototype.toJSON()
JSON.parse(text, reviver?)
JSON.parse(text, reviver?)解析text中的 JSON 数据并返回 JavaScript 值。以下是一些示例 JSON.parse(String) // illegal quotes
SyntaxError: Unexpected token ILLEGALJSON.parse(String)
StringJSON.parse(123)
123JSON.parse([1, 2, 3])
[ 1, 2, 3 ]JSON.parse({ hello: 123, world: 456 })
{ hello: 123, world: 456 }可选参数reviver是一个节点访问者参见通过节点访问者转换数据可用于转换解析后的数据。在此示例中我们将日期字符串转换为日期对象
function dateReviver(key, value) {if (typeof value string) {var x Date.parse(value);if (!isNaN(x)) { // valid date string?return new Date(x);}}return value;
}以下是交互 var str { name: John, birth: 2011-07-28T22:00:00.000Z };JSON.parse(str, dateReviver)
{ name: John, birth: Thu, 28 Jul 2011 22:00:00 GMT }通过节点访问者转换数据
JSON.stringify()和JSON.parse()都允许您通过传递函数来转换 JavaScript 数据 JSON.stringify()允许您在将其转换为 JSON 之前更改 JavaScript 数据。 JSON.parse()解析 JSON然后让您对生成的 JavaScript 数据进行后处理。
JavaScript 数据是一个树其复合节点是数组和对象其叶子是原始值布尔值数字字符串null。让我们将传递的转换函数称为节点访问者。这些方法遍历树并为每个节点调用访问者。然后可以选择替换或删除节点。节点访问者的签名如下
function nodeVisitor(key, value)参数是
this
当前节点的父节点。
key
当前节点位于其父节点内的键。key 总是一个字符串。
值
当前节点。
根节点 root 没有父节点。当访问 root 时为其创建了一个伪父节点并且参数具有以下值 this 是 { : root }。 key 是 。 value 是 root。
节点访问者有三种返回值的选项 返回 value然后不执行任何更改。 返回不同的值。然后当前节点被替换。 返回 undefined。然后移除节点。
以下是节点访问者的示例。它记录了传递给它的值。
function nodeVisitor(key, value) {console.log([// Use JSON.stringify for nicer-looking outputJSON.stringify(this), // parentJSON.stringify(key),JSON.stringify(value)].join( # ));return value; // dont change node
}让我们使用此函数来检查 JSON 方法如何迭代 JavaScript 数据。
JSON.stringify()
特殊的根节点首先出现在前缀迭代中父节点在子节点之前。访问的第一个节点始终是伪根。在每次调用后显示的最后一行是 stringify() 返回的字符串 JSON.stringify([a,b], nodeVisitor)
{:[a,b]} # # [a,b]
[a,b] # 0 # a
[a,b] # 1 # b
[a,b] JSON.stringify({a:1, b:2}, nodeVisitor)
{:{a:1,b:2}} # # {a:1,b:2}
{a:1,b:2} # a # 1
{a:1,b:2} # b # 2
{a:1,b:2} JSON.stringify(abc, nodeVisitor)
{:abc} # # abc
abcJSON.parse()
首先是叶子节点在后缀迭代中子节点在父节点之前。访问的最后一个节点始终是伪根。在每次调用后显示的最后一行是 parse() 返回的 JavaScript 值 JSON.parse([a,b], nodeVisitor)
[a,b] # 0 # a
[a,b] # 1 # b
{:[a,b]} # # [a,b]
[ a, b ] JSON.parse({a:1, b:2}, nodeVisitor)
{a:1,b:2} # a # 1
{a:1,b:2} # b # 2
{:{a:1,b:2}} # # {a:1,b:2}
{ a: 1, b: 2 } JSON.parse(hello, nodeVisitor)
{:hello} # # hello
hello第二十三章标准全局变量 原文23. Standard Global Variables 译者飞龙 协议CC BY-NC-SA 4.0 本章是 ECMAScript 规范标准化的全局变量的参考。Web 浏览器有更多全局变量这些变量在 MDN 上列出。所有全局变量都是全局对象的自有或继承的属性在浏览器中是 window参见 全局对象。
构造函数
有关以下构造函数的详细信息请参见括号中指示的部分 Array[数组构造函数](ch18.html#array_constructor “数组构造函数” Boolean[原始值的包装对象](ch08.html#wrapper_objects “原始值的包装对象” Date[日期构造函数](ch20.html#date_constructors “日期构造函数” Function[使用 new Function() 评估代码](ch23.html#function_constructor “使用 new Function() 评估代码” Number[原始值的包装对象](ch08.html#wrapper_objects “原始值的包装对象” 对象[将任何值转换为对象](ch17_split_000.html#toobject “将任何值转换为对象” RegExp[创建正则表达式](ch19.html#creating_regexps “创建正则表达式” String[原始值的包装对象](ch08.html#wrapper_objects “原始值的包装对象”
错误构造函数
有关这些构造函数的详细信息请参见 [错误构造函数](ch14.html#error_constructors “错误构造函数” Error EvalError RangeError ReferenceError SyntaxError TypeError URIError
非构造函数
有几个全局函数不是构造函数。它们在本节中列出。
编码和解码文本
以下函数处理 URI 编码和解码的几种方式
encodeURI(uri)
在 uri 中对特殊字符进行百分比编码。特殊字符是除以下字符外的所有 Unicode 字符
URI 字符; , / ? : $ #未编码a-z A-Z 0-9 - _ . ! ~ * ( )
例如 encodeURI(http://example.com/Für Elise/)
http://example.com/F%C3%BCr%20Elise/encodeURIComponent(uriComponent)
在 uriComponent 中对所有字符进行百分比编码除了
| 未编码 | a-z A-Z 0-9 - _ . ! ~ * ( ) |
与 encodeURI 相反URL 和文件名中有意义的字符也被编码了。因此您可以使用此函数将任何文本转换为合法的文件名或 URL 路径段。例如 encodeURIComponent(http://example.com/Für Elise/)
http%3A%2F%2Fexample.com%2FF%C3%BCr%20Elise%2FdecodeURI(encodedURI)
解码由 encodeURI 生成的百分比编码的 URI decodeURI(http://example.com/F%C3%BCr%20Elise/)
http://example.com/Für Elise/encodeURI 不会对 URI 字符进行编码decodeURI 也不会对其进行解码即使它们已经被正确编码 decodeURI(%2F)
%2FdecodeURIComponent(%2F)
/decodeURIComponent(encodedURIComponent)
解码由 encodeURIComponent 生成的百分比编码的 URI 组件。与 decodeURI 相反所有百分比编码的字符都被解码 decodeURIComponent(http%3A%2F%2Fexample.com%2FF%C3%BCr%20Elise%2F)
http://example.com/Für Elise/以下内容已被弃用 escape(str)对str进行百分比编码。它已被弃用因为它不能正确处理非 ASCII 字符。请改用encodeURIComponent()。 unescape(str)对str进行百分比解码。它已被弃用因为它不能正确处理非 ASCII 字符。请改用decodeURIComponent()。
对数字进行分类和解析
以下方法有助于对数字进行分类和解析 isFinite(number) (检查是否为无穷大) isNaN(value) (陷阱检查值是否为 NaN) parseFloat(string) (parseFloat()) parseInt(string, radix) (通过 parseInt()获取整数)
通过 eval()和 new Function()动态评估 JavaScript 代码
本节将介绍如何在 JavaScript 中动态评估代码。
使用 eval()评估代码
函数调用
eval(str)评估str中的 JavaScript 代码。例如 var a 12;eval(a 5)
17请注意eval()在语句上下文中解析参见表达式与语句 eval({ foo: 123 }) // code block
123eval(({ foo: 123 })) // object literal
{ foo: 123 }在严格模式下使用 eval()
对于eval()您确实应该使用严格模式参见严格模式。在松散模式下评估的代码可以在周围范围内创建局部变量
function sloppyFunc() {eval(var foo 123); // added to the scope of sloppyFuncconsole.log(foo); // 123
}在严格模式下无法发生
function strictFunc() {use strict;eval(var foo 123);console.log(foo); // ReferenceError: foo is not defined
}然而即使在严格模式下评估的代码仍然可以读取和写入周围范围内的变量。要防止这种访问您需要间接调用eval()。
间接 eval()在全局范围内进行评估
有两种调用eval()的方法 直接。通过直接调用名称为“eval”的函数。 间接调用。以其他方式通过call()作为window的方法通过在不同名称下存储它并在那里调用等。
正如我们已经看到的直接eval()在当前范围内执行代码
var x global;function directEval() {use strict;var x local;console.log(eval(x)); // local
}相反间接eval()在全局范围内执行它
var x global;function indirectEval() {use strict;var x local;// Don’t call eval directlyconsole.log(eval.call(null, x)); // globalconsole.log(window.eval(x)); // globalconsole.log((1, eval)(x)); // global (1)// Change the name of evalvar xeval eval;console.log(xeval(x)); // global// Turn eval into a methodvar obj { eval: eval };console.log(obj.eval(x)); // global
}1的解释当您通过名称引用变量时初始结果是所谓的引用一个具有两个主要字段的数据结构 base指向环境即变量值存储的数据结构。 referencedName是变量的名称。
在eval()函数调用期间函数调用运算符括号遇到对eval的引用并且可以确定要调用的函数的名称。因此这样的函数调用触发了直接的eval()。但是您可以通过不给出调用运算符的引用来强制间接eval()。这是通过在应用运算符之前检索引用的值来实现的。逗号运算符在第1行为我们执行此操作。此运算符评估第一个操作数并返回评估第二个操作数的结果。评估始终产生值这意味着引用被解析并丢失了函数名称。
间接评估的代码总是松散的。这是代码独立于其当前环境进行评估的结果
function strictFunc() {use strict;var code (function () { return this }());var result eval.call(null, code);console.log(result ! undefined); // true, sloppy mode
}使用 new Function()评估代码
构造函数Function()的签名为
new Function(param1, ..., paramN, funcBody)它创建一个函数其零个或多个参数的名称为param1parem2等其主体为funcBody也就是说创建的函数如下所示
function («param1», ..., «paramN») {«funcBody»
}让我们使用new Function()创建一个函数f它返回其参数的总和 var f new Function(x, y, return xy);f(3, 4)
7类似于间接eval()new Function()创建其作用域为全局的函数:¹⁶
var x global;function strictFunc() {use strict;var x local;var f new Function(return x);console.log(f()); // global
}这样的函数默认情况下也是松散的
function strictFunc() {use strict;var sl new Function(return this);console.log(sl() ! undefined); // true, sloppy modevar st new Function(use strict; return this);console.log(st() undefined); // true, strict mode
}eval()与 new Function()
通常最好使用new Function()而不是eval()来评估代码函数参数为评估的代码提供了清晰的接口而且你不需要间接eval()的略显笨拙的语法来确保评估的代码只能访问全局变量除了它自己的变量。
最佳实践
你不应该使用eval()和new Function()。动态评估代码很慢而且存在潜在的安全风险。它还会阻止大多数使用静态分析的工具如 IDE考虑代码。
通常有更好的替代方案。例如Brendan Eich 最近在推特上发推文指出了程序员们使用的反模式他们想要访问存储在变量propName中的属性
var value eval(obj.propName);这个想法是有道理的点运算符只支持固定的静态提供的属性键。在这种情况下属性键只在运行时知道这就是为什么需要eval()来使用该运算符。幸运的是JavaScript 还有方括号运算符它接受动态属性键。因此以下是前面代码的更好版本
var value obj[propName];你也不应该使用eval()或new Function()来解析 JSON 数据。这是不安全的。要么依赖 ECMAScript 5 对 JSON 的内置支持参见第二十二章要么使用一个库。
合法的用例
eval()和new Function()有一些合法的尽管是高级的用例带有函数的配置数据JSON 不允许模板库解释器命令行和模块系统。
结论
这是 JavaScript 动态评估代码的一个相对高级的概述。如果你想深入了解可以查看 kangax 的文章“全局 eval。有哪些选项”。
控制台 API
在大多数 JavaScript 引擎中有一个全局对象console其中包含用于记录和调试的方法。该对象不是语言本身的一部分但已成为事实上的标准。由于它们的主要目的是调试console方法在开发过程中最常用而在部署的代码中很少使用。
本节概述了控制台 API。它记录了 Chrome 32、Firebug 1.12、Firefox 25、Internet Explorer 11、Node.js 0.10.22 和 Safari 7.0 的现状。
控制台 API 在各种引擎之间的标准化程度如何
控制台 API 的实现差异很大而且不断变化。如果你想要权威的文档你有两个选择。首先你可以查看 API 的标准概述 Firebug 首先实现了控制台 API其在其维基中的文档是目前最接近标准的东西。 此外Brian Kardell 和 Paul Irish 正在制定API 规范这应该会导致更一致的行为。
其次你可以查看各种引擎的文档 Chrome Firebug Firefox Internet Explorer Node.js Safari
警告
在 Internet Explorer 9 中存在一个错误。在该浏览器中只有开发者工具至少打开过一次console对象才存在。这意味着如果在工具打开之前引用console你会得到一个ReferenceError。作为一种解决方法你可以检查console是否存在如果不存在则创建一个虚拟实现。
简单的日志记录
控制台 API 包括以下记录方法
console.clear()
清除控制台。
console.debug(object1, object2?, ...)
最好使用console.log()它与此方法相同。
console.error(object1, object2?, ...)
将参数记录到控制台。在浏览器中记录的内容可能会被“错误”图标标记和/或包括堆栈跟踪或代码链接。
console.exception(errorObject, object1?, ...]) [仅限 Firebug]
记录object1等并显示交互式堆栈跟踪。
console.info(object1?, object2?, ...)
将参数记录到控制台。在浏览器中记录的内容可能会被“信息”图标标记和/或包括堆栈跟踪或代码链接。
console.log(object1?, object2?, ...)
将参数记录到控制台。如果第一个参数是printf风格的格式字符串则使用它来打印其余的参数。例如Node.js REPL console.log(%s, { foo: bar })
[object Object]console.log(%j, { foo: bar })
{foo:bar}唯一可靠的跨平台格式化指令是%s。Node.js 支持%j以将数据格式化为 JSON浏览器倾向于支持记录交互内容的指令。
console.trace()
记录堆栈跟踪在许多浏览器中是交互式的。
console.warn(object1?, object2?, ...)
将参数记录到控制台。在浏览器中记录的内容可能会被“警告”图标标记和/或包括堆栈跟踪或代码链接。
在以下表中指出了各种平台的支持
ChromeFirebugFirefoxIENode.jsSafariclear✓✓✓✓debug✓✓✓✓✓error✓✓✓✓✓✓exception✓info✓✓✓✓✓✓log✓✓✓✓✓✓trace✓✓✓✓✓✓warn✓✓✓✓✓✓
exception以斜体排版因为它只在单个平台上受支持。
检查和计数
控制台 API 包括以下检查和计数方法
console.assert(expr, obj?)
如果expr为false则将obj记录到控制台并抛出异常。如果为true则什么也不做。
console.count(label?)
计算带有此语句的行被执行的次数。
在以下表中指出了各种平台的支持
ChromeFirebugFirefoxIENode.jsSafariassert✓✓✓✓✓count✓✓✓✓
格式化日志
控制台 API 包括以下格式化日志的方法
console.dir(object)
将对象的表示打印到控制台。在浏览器中该表示可以交互地进行探索。
console.dirxml(object)
打印 HTML 或 XML 元素的 XML 源树。
console.group(object1?, object2?, ...)
将对象记录到控制台并打开一个包含所有未来记录内容的嵌套块。通过调用console.groupEnd()来关闭该块。该块最初是展开的但可以折叠。
console.groupCollapsed(object1?, object2?, ...)
类似于console.group()但是该块最初是折叠的。
console.groupEnd()
关闭由console.group()或console.groupCollapsed()打开的组。
console.table(data, columns?)
将数组打印为表格每行一个元素。可选参数columns指定在列中显示哪些属性/数组索引。如果缺少该参数则所有属性键都将用作表格列。缺少的属性和数组元素显示为列中的undefined
var persons [{ firstName: Jane, lastName: Bond },{ firstName: Lars, lastName: Croft, age: 72 }
];
// Equivalent:
console.table(persons);
console.table(persons, [firstName, lastName, age]);结果表如下
(索引)名字姓氏年龄0“Jane”“Bond”undefined1“Lars”“Croft”72
在以下表中指出了各种平台的支持
ChromeFirebugFirefoxIENode.jsSafaridir✓✓✓✓✓✓dirxml✓✓✓✓group✓✓✓✓✓groupCollapsed✓✓✓✓✓groupEnd✓✓✓✓✓table✓✓
分析和计时
控制台 API 包括以下用于分析和计时的方法
控制台.标记时间线标签 [仅限 Safari]
与console.timeStamp相同。
控制台.性能标题
打开分析。可选的title用于分析报告。
控制台.分析结束()
停止分析并打印分析报告。
控制台.时间标签
启动标签为label的计时器。
控制台.时间结束标签
停止标签为label的计时器并打印自启动以来经过的时间。
控制台.时间戳标签
记录具有给定label的时间戳。可以记录到控制台或时间轴。
以下表格显示了各种平台上的支持
ChromeFirebugFirefoxIENode.jsSafarimarkTimeline✓profile✓✓(devtools)✓✓profileEnd✓✓(devtools)✓✓time✓✓✓✓✓✓timeEnd✓✓✓✓✓✓timeStamp✓✓
markTimeline以斜体排版因为它仅在单个平台上受支持。 devtools表示必须打开开发人员工具才能使该方法起作用。¹⁷
命名空间和特殊值
以下全局变量用作函数的命名空间。有关详细信息请参阅括号中指示的材料
JSON
JSON API 功能[第二十二章](ch22.html “第二十二章.JSON”
数学
数学 API 功能[第二十一章](ch21.html “第二十一章.数学”
对象
元编程功能[对象操作小抄使用对象](ch17_split_001.html#oop_cheat_sheet “对象操作小抄使用对象”
以下全局变量包含特殊值。有关更多信息请查看括号中指示的材料
未定义
表示某物不存在的值[未定义和 null](ch08.html#undefined_null “未定义和 null” ({}.foo) undefined
trueNaN
一个表示某物是“非数字”[NaN](ch11.html#nan “NaN”的值 1 / abc
NaN无穷大
表示数值无穷大∞的值[无穷大](ch11.html#infinity “无穷大” 1 / 0
Infinity¹⁶ Mariusz Nowakmedikoo告诉我由Function评估的代码默认情况下在任何地方都是松散的。
¹⁷ 感谢 Matthias Reutergweax和 Philipp Kyeckpkyeck对本节的贡献。
第二十四章 Unicode 和 JavaScript 原文24. Unicode and JavaScript 译者飞龙 协议CC BY-NC-SA 4.0 本章是对 Unicode 及其在 JavaScript 中的处理的简要介绍。
Unicode 历史
Unicode 始于 1987 年由 Joe Becker施乐Lee Collins苹果和 Mark Davis苹果发起。其想法是创建一个通用字符集因为当时对于编码纯文本存在许多不兼容的标准许多变体的 8 位 ASCIIBig Five繁体中文GB 2312简体中文等。在 Unicode 之前没有多语言纯文本的标准但有丰富的文本系统例如苹果的 WorldScript允许您组合多个编码。
第一份 Unicode 草案提案于 1988 年发布。此后继续工作并扩大工作组。Unicode 联盟于 1991 年 1 月 3 日成立 Unicode 联盟是一家致力于开发、维护和推广软件国际化标准和数据的非营利性公司特别是 Unicode 标准[…] Unicode 1.0 标准的第一卷于 1991 年 10 月出版第二卷于 1992 年 6 月出版。
重要的 Unicode 概念
字符的概念可能看起来很简单但它有许多方面。这就是为什么 Unicode 是一个如此复杂的标准。以下是重要的基本概念
字符和字形
这两个术语的意思相似。字符是数字实体而字形是书面语言的原子单位字母、印刷连字、中文字符、标点符号等。程序员以字符为思考单位而用户以字形为思考单位。有时需要使用多个字符来表示单个字形。例如我们可以通过组合字符o和字符^抑扬符来产生单个字形ô。
字形
这是一种显示字形的具体方式。有时相同的字形在不同的上下文或其他因素下显示方式不同。例如字形f和i可以呈现为字形f和字形i通过连字字形连接或者没有连字。
代码点
Unicode 通过称为代码点的数字来表示它支持的字符。代码点的十六进制范围是 0x0 到 0x10FFFF17 倍 16 位。
代码单元
为了存储或传输代码点我们将它们编码为代码单元这是具有固定长度的数据片段。长度以位为单位并由编码方案确定Unicode 有几种编码方案例如 UTF-8 和 UTF-16。名称中的数字表示代码单元的长度以位为单位。如果一个代码点太大而无法适应单个代码单元它必须被分解为多个单元也就是说表示单个代码点所需的代码单元数量可能会有所不同。
BOM字节顺序标记
如果一个代码单元大于一个字节字节顺序很重要。BOM 是文本开头的一个伪字符可能被编码为多个代码单元指示代码单元是大端最重要的字节在前还是小端最不重要的字节在前。没有 BOM 的文本的默认值是大端。BOM 还指示所使用的编码对于 UTF-8、UTF-16 等编码是不同的。此外如果 Web 浏览器没有关于文本编码的其他信息它还可以作为 Unicode 的标记。然而由于几个原因BOM 并不经常使用 UTF-8 是迄今为止最流行的 Unicode 编码不需要 BOM因为只有一种字节排序方式。 几种字符编码规定了固定的字节顺序。那么就不应该使用 BOM。例如 UTF-16BEUTF-16 大端、UTF-16LE、UTF-32BE 和 UTF-32LE。这是处理字节顺序的更安全的方式因为元数据和数据保持分开不会混淆。
规范化
有时相同的字形可以用几种方式表示。例如字形ö可以表示为单个代码点也可以表示为一个o后跟一个组合字符¨分音符双点。规范化是将文本转换为规范表示的过程等效的代码点和代码点序列都被转换为相同的代码点或代码点序列。这对于文本处理例如搜索文本很有用。Unicode 规定了几种规范化。
字符属性
规范指定了规范的几个属性其中一些列在这里 名称。一个由大写字母 A-Z数字 0-9连字符(-)和空格组成的英文名称。两个例子 “λ”的名称是“希腊小写字母λ”。 “!”的名称是“感叹号”。 一般类别。将字符分成字母、大写字母、数字和标点等类别。 年龄。该字符是在哪个版本的 Unicode 中引入的1.0、1.1、2.0 等 已弃用。是否不鼓励使用该字符 以及更多。
代码点
代码点的范围最初是 16 位。随着 Unicode 版本 2.01996 年 7 月的扩展它现在被分成了 17 个平面编号从 0 到 16。每个平面包括 16 位十六进制表示法0x0000–0xFFFF。因此在接下来的十六进制范围中四个底部以外的数字包含了平面的编号。 第 0 平面基本多文种平面BMP0x0000–0xFFFF 第 1 平面补充多语种平面SMP0x10000–0x1FFFF 第 2 平面补充表意文字平面SIP0x20000–0x2FFFF 第 3–13 平面未分配 第 14 平面补充特殊用途平面SSP0xE0000–0xEFFFF 第 15–16 平面补充专用区域S PUA A/B0x0F0000–0x10FFFF
第 1–16 平面称为补充平面或星际平面。
Unicode 编码
UTF-32Unicode 转换格式 32是一种具有 32 位代码单元的格式。任何代码点都可以由单个代码单元编码使得这是唯一的固定长度编码对于其他编码编码一个点所需的单元数量是变化的。
UTF-16是一种具有 16 位代码单元的格式需要一个到两个单元来表示一个代码点。BMP 代码点可以由单个代码单元表示。高代码点是 20 位16 乘以 16 位在减去 0x10000BMP 的范围后。这些位被编码为两个代码单元所谓的代理对
领先代理
最重要的 10 位存储在范围 0xD800–0xDBFF 中。也称为高代理代码单元。
尾随代理
最不重要的 10 位存储在范围 0xDC00–0xDFFF 中。也称为低代理代码单元。
以下表格改编自 Unicode 标准 6.2.0表 3-5可视化了位的分布
代码点UTF-16 代码单元xxxxxxxxxxxxxxxx16 位xxxxxxxxxxxxxxxxpppppxxxxxxyyyyyyyyyy21 位5610 位110110qqqqxxxxxx 110111yyyyyyyyyyqqqq ppppp − 1
为了启用这种编码方案BMP 有一个未使用的代码点范围为 0xD800–0xDFFF 的空隙。因此领先代理、尾随代理和 BMP 代码点的范围是不相交的使得在面对错误时解码更加健壮。以下函数将代码点编码为 UTF-16稍后我们将看到一个使用它的示例
function toUTF16(codePoint) {var TEN_BITS parseInt(1111111111, 2);function u(codeUnit) {return \\ucodeUnit.toString(16).toUpperCase();}if (codePoint 0xFFFF) {return u(codePoint);}codePoint - 0x10000;// Shift right to get to most significant 10 bitsvar leadingSurrogate 0xD800 | (codePoint 10);// Mask to get least significant 10 bitsvar trailingSurrogate 0xDC00 | (codePoint TEN_BITS);return u(leadingSurrogate) u(trailingSurrogate);
}UCS-2一种已弃用的格式使用 16 位代码单元来表示仅BMP 的代码点。当 Unicode 代码点的范围扩展到 16 位之外时UTF-16 取代了 UCS-2。
UTF-8具有 8 位代码单元。它在传统 ASCII 编码和 Unicode 之间架起了一座桥梁。ASCII 只有 128 个字符其编号与前 128 个 Unicode 代码点相同。UTF-8 是向后兼容的因为所有 ASCII 代码都是有效的代码单元。换句话说在范围 0–127 的单个代码单元中编码了相同范围内的单个代码点。这些代码单元的最高位为零。另一方面如果最高位为 1则会跟随更多的单元以为更高的代码点提供额外的位。这导致了以下编码方案 0000–007F0xxxxxxx7 位存储在 1 字节中 0080–07FF110xxxxx10xxxxxx56 位11 位存储在 2 字节中 0800–FFFF1110xxxx10xxxxxx10xxxxxx466 位16 位存储在 3 字节中 10000–1FFFFF11110xxx10xxxxxx10xxxxxx10xxxxxx3666 位21 位存储在 4 字节中。最高代码点是 10FFFF因此 UTF-8 有一些额外的空间。
如果最高位不为 0则零之前的 1 的数量表示序列中有多少个代码单元。初始单元之后的所有单元都具有位前缀 10。因此初始代码单元和后续代码单元的范围是不相交的这有助于从编码错误中恢复。
UTF-8 已成为最流行的 Unicode 格式。最初它之所以受欢迎是因为它与 ASCII 的向后兼容性。后来它因其在操作系统、编程环境和应用程序中的广泛和一致的支持而受到青睐。
JavaScript 源代码和 Unicode
JavaScript 处理 Unicode 源代码有两种方式内部在解析期间和外部在加载文件时。
内部源代码
在内部JavaScript 源代码被视为一系列 UTF-16 代码单元。根据第 6 节的 EMCAScript 规范 ECMAScript 源文本以 Unicode 字符编码的形式表示版本为 3.0 或更高。[…] ECMAScript 源文本被假定为本规范的目的是一系列 16 位代码单元。[…] 如果实际源文本以除 16 位代码单元以外的形式编码必须处理为首先转换为 UTF-16。 在标识符、字符串文字和正则表达式文字中任何代码单元也可以通过 Unicode 转义序列\uHHHH来表示其中HHHH是四个十六进制数字。例如 var f\u006F\u006F abc;foo
abc var λ 123;\u03BB
123这意味着您可以在源代码中使用 Unicode 字符的文字和变量名而不会离开 ASCII 范围。
在字符串文字中还有一种额外的转义可用用两位十六进制数字表示的十六进制转义序列表示范围在 0x00-0xFF 的代码单元。例如 \xF6 ö
true\xF6 \u00F6
true外部源代码
虽然内部使用 UTF-16但 JavaScript 源代码通常不以该格式存储。当 Web 浏览器通过script标签加载源文件时它会确定编码如下 如果文件以 BOM 开头则编码是 UTF 变体取决于使用的 BOM。 否则如果文件是通过 HTTP(S)加载的那么Content-Type头可以通过charset参数指定编码。例如 Content-Type: application/javascript; charsetutf-8提示
JavaScript 文件的正确媒体类型以前称为MIME 类型是application/javascript。但是较旧的浏览器例如 Internet Explorer 8 及更早版本最可靠地使用text/javascript。不幸的是script标签的type属性的默认值是text/javascript。至少对于 JavaScript您可以省略该属性包含它没有好处。 否则如果script标签具有charset属性则将使用该编码。即使属性type包含有效的媒体类型该类型也不得具有参数charset就像前述的Content-Type头。这确保了charset和type的值不会冲突。 否则使用包含script标签的文档的编码。例如这是 HTML5 文档的开头其中meta标签声明文档编码为 UTF-8 !doctype html
html
headmeta charsetUTF-8
...强烈建议您始终指定编码。如果不指定将使用特定于区域设置的默认编码。换句话说在不同国家人们将以不同方式看待文件。只有最低的 7 位在各个区域设置中相对稳定。
我的建议可以总结如下 对于您自己的应用程序您可以使用 Unicode。但必须将应用程序的 HTML 页面的编码指定为 UTF-8。 对于库最安全的做法是发布 ASCII7 位代码。
一些缩小工具可以将具有超出 7 位的 Unicode 代码点的源代码转换为“7 位干净”的源代码。它们通过用 Unicode 转义替换非 ASCII 字符来实现。例如以下调用UglifyJS将文件test.js翻译为
uglifyjs -b beautifyfalse,ascii-onlytrue test.js文件test.js如下所示
var σ Köln;UglifyJS 的输出如下
var \u03c3K\xf6ln;考虑以下负面示例。有一段时间库 D3.js 以 UTF-8 发布。这导致了一个错误因为当它从编码不是 UTF-8 的页面加载时代码包含了诸如以下语句
var π Math.PI, ε 1e-6;标识符π和ε没有被正确解码也没有被识别为有效的变量名。此外一些超出 7 位的代码点的字符串文字也没有被正确解码。作为一种解决方法您可以通过向script标签添加适当的charset属性来加载代码
script charsetutf-8 srcd3.js/scriptJavaScript 字符串和 Unicode
JavaScript 字符串是一系列 UTF-16 代码单元。根据 ECMAScript 规范第 8.4 节 当一个字符串包含实际文本数据时每个元素被认为是单个 UTF-16 代码单元。 转义序列
如前所述您可以在字符串文字中使用 Unicode 转义序列和十六进制转义序列。例如您可以通过将o与重音符代码点 0x0308组合来产生字符ö console.log(o\u0308)
ö这适用于 JavaScript 命令行例如 Web 浏览器控制台和 Node.js REPL。您还可以将这种类型的字符串插入到 Web 页面的 DOM 中。
通过转义引用星际飞机字符
网络上有许多不错的 Unicode 符号表。看看 Tim Whitlock 的“Emoji Unicode Tables”并对现代 Unicode 字体中有多少符号感到惊讶。表中的符号都不是图像它们都是字体字形。假设您想通过 JavaScript 显示一个星际飞机中的 Unicode 字符显然这样做存在风险并非所有字体都支持所有这些字符。例如考虑一头奶牛代码点为 0x1F404。
您可以复制字符并直接粘贴到您的 Unicode 编码 JavaScript 源代码中 JavaScript 引擎将解码源代码通常为 UTF-8并创建一个具有两个 UTF-16 代码单元的字符串。或者您可以自己计算两个代码单元并使用 Unicode 转义序列。有一些网络应用程序可以执行这种计算例如 UTF 转换器 Mathias Bynens 的“JavaScript 转义”
先前定义的函数toUTF16也执行了它 toUTF16(0x1F404)
\\uD83D\\uDC04UTF-16 代理对0xD83D0xDC04确实编码了奶牛 计数字符
如果字符串包含代理对两个编码单元编码一个代码点那么length属性不再计算图形元素。它计算编码单元 这可以通过库来修复例如 Mathias Bynens 的Punycode.js它与 Node.js 捆绑在一起 var puny require(punycode);puny.ucs2.decode(str).length
1Unicode 规范化
如果您想在字符串中搜索或比较它们那么您需要进行规范化例如通过库unorm由 Bjarke Walling。
JavaScript 正则表达式和 Unicode
JavaScript 正则表达式中的 Unicode 支持请参阅第十九章非常有限。例如没有办法匹配“大写字母”等 Unicode 类别。
行终止符影响匹配。行终止符是下表中指定的四个字符之一
代码单元名称字符转义序列\u000A换行符\n\u000D回车\r\u2028行分隔符\u2029段落分隔符
以下正则表达式构造基于 Unicode \s \S空白非空白具有基于 Unicode 的定义 /^\s$/.test(\uFEFF)
true.点匹配所有代码单元不是代码点除了行终止符。请参阅下一节了解如何匹配任何代码点。 多行模式/m在多行模式下断言^匹配输入的开头和行终止符之后。断言$匹配行终止符之前和输入的结尾。在非多行模式下它们只在输入的开头或结尾匹配。
其他重要的字符类是基于 ASCII 而不是 Unicode 定义的 \d \D数字非数字数字等同于[0-9]。 \w \W单词字符非单词字符单词字符等同于[A-Za-z0-9_]。 \b \B在单词边界单词内单词是由单词字符[A-Za-z0-9_]组成的序列。例如在字符串über中字符类转义\b将字符b视为单词的开始 /\bb/.test(über)
true匹配任何代码单元和任何代码点
要匹配任何代码单元您可以使用[\s\S]请参见原子通用。
要匹配任何代码点您需要使用¹⁸
([\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF])前面的模式工作原理如下
([BMP code point]|[leading surrogate][trailing surrogate])由于所有这些范围都是不相交的该模式将正确匹配 UTF-16 字符串中的代码点。
库
一些库可帮助处理 JavaScript 中的 Unicode Regenerate有助于生成像前面那样的范围以匹配任何代码单元。它旨在用作构建工具的一部分但也可以动态工作用于尝试各种功能。 XRegExp是一个正则表达式库它有一个官方附加组件可以通过以下三种构造之一匹配 Unicode 类别、脚本、块和属性 \p{...} \p{^...} \P{...}例如\p{Letter}匹配各种字母表中的字母而\p{^Letter}和\P{Letter}都匹配所有其他代码点。第三十章包含了对 XRegExp 的简要概述。
ECMAScript 国际化 API请参见ECMAScript 国际化 API提供了对 Unicode 的排序和搜索等功能。
推荐阅读和章节来源
有关 Unicode 的更多信息请参见以下内容 维基百科上有几篇关于Unicode及其术语的好文章。 Unicode.orgUnicode 联盟的官方网站以及其FAQ也是很好的资源。 Joel Spolsky 的介绍性文章“每个软件开发人员绝对必须了解的有关 Unicode 和字符集的绝对最低限度没有借口”很有帮助。
有关 JavaScript 中的 Unicode 支持的信息请参见 Mathias Bynens 的文章“JavaScript 的内部字符编码UCS-2 还是 UTF-16” 《JavaScript正则表达式和 Unicode》由 Steven Levithan
致谢
以下人员为本章做出了贡献Mathias BynensmathiasAnne van Kesterenannevk和 Calvin MetcalfCWMma。 ¹⁸ 严格来说任何Unicode 标量值。
第二十五章ECMAScript 5 中的新功能 原文25. New in ECMAScript 5 译者飞龙 协议CC BY-NC-SA 4.0 本章列出了仅在 ECMAScript 5 中可用的功能。如果您必须使用旧版 JavaScript 引擎您应该避免使用这些功能或者通过库启用其中一些功能稍后将进行描述。请注意通常情况下本书假定您正在使用完全支持 ECMAScript 5 的现代引擎。
ECMAScript 5 规范包含了对其范围的以下描述 ECMAScript 的第五版作为 ECMA-262 第 5 版发布 对已成为浏览器实现中常见的语言规范的实际解释进行了编码 增加了对自第三版出版以来出现的新功能的支持。这些功能包括 访问器属性 反射创建和检查对象 程序控制属性属性 附加数组操作函数 对 JSON 对象编码格式的支持以及 x 提供增强的错误检查和程序安全性的严格模式。 新功能
ECMAScript 5 中包含的新功能如下
严格模式参见严格模式
将以下行放在文件或函数的开头可以打开所谓的严格模式使 JavaScript 成为一个更干净的语言禁止一些功能执行更多检查并抛出更多异常
use strict;访问器参见访问器Getter 和 Setter
Getter 和 setter 允许您通过方法实现属性的获取和设置。例如以下对象obj包含属性foo的 getter var obj { get foo() { return abc } };obj.foo
abc语法更改
ECMAScript 5 包括以下语法更改
保留字作为属性键
您可以在点运算符之后使用保留字例如new和function并且在对象文字中作为非引用的属性键 var obj { new: abc };obj.new
abc合法的尾随逗号
对象文字和数组文字中的尾随逗号是合法的。
多行字符串文字
如果通过反斜杠转义行尾字符串文字可以跨多行。
标准库中的新功能
ECMAScript 5 为 JavaScript 的标准库带来了几个新增功能。本节按类别列出了它们。
元编程
获取和设置原型参见获取和设置原型 Object.create() Object.getPrototypeOf()
通过属性描述符管理属性属性参见属性描述符 Object.defineProperty() Object.defineProperties() Object.create() Object.getOwnPropertyDescriptor()
列出属性参见迭代和属性检测 Object.keys() Object.getOwnPropertyNames()
保护对象参见保护对象 Object.preventExtensions() Object.isExtensible() Object.seal() Object.isSealed() Object.freeze() Object.isFrozen()
新的Function方法参见Function.prototype.bind(thisValue, arg1?, …, argN?)
Function.prototype.bind()
新方法
字符串参见第十二章 新方法String.prototype.trim() 通过方括号操作符[...]访问字符
新的Array方法参见[Array Prototype Methods](ch18.html#array_prototype_methods “Array Prototype Methods” Array.isArray() Array.prototype.every() Array.prototype.filter() Array.prototype.forEach() Array.prototype.indexOf() Array.prototype.lastIndexOf() Array.prototype.map() Array.prototype.reduce() Array.prototype.some()
新的Date方法参见Date Prototype Methods Date.now() Date.prototype.toISOString()
JSON
对 JSON 的支持参见第二十二章 JSON.parse()参见JSON.parse(text, reviver?) JSON.stringify()参见JSON.stringify(value, replacer?, space?) 一些内置对象具有特殊的toJSON()方法 Boolean.prototype.toJSON() Number.prototype.toJSON() String.prototype.toJSON() Date.prototype.toJSON()
与旧版浏览器一起工作的提示
如果您需要与旧版浏览器一起工作以下资源将非常有用 Juriy Zaytsev“kangax”的兼容性表显示了各种浏览器的各个版本支持 ECMAScript 5 的程度。 es5-shim 将 ECMAScript 5 的大部分但不是全部功能带到只支持 ECMAScript 3 的浏览器中。