高级 JavaScript(二)

来源:互联网 发布:沙特 知乎 编辑:程序博客网 时间:2024/06/05 07:30

集合 (JavaScript)

可以使用集合对象 Map、Set 和 WeakMap 存储值和对象。通过这些对象,可以使用键或值而非索引来轻松添加和检索成员。若要使用索引访问集合的成员,请使用 Array 对象。有关详细信息,请参阅使用数组 (JavaScript)。

使用集合

Map 和 WeakMap 对象存储键/值对,并使你能够通过使用键来添加、检索和移除成员。键和值可以为任何类型。 Set 对象存储任何类型的值。

通过 Map 和 Set 对象,你能够使用 forEach 方法枚举集合成员,并使用 size 方法检查集合大小。与此相反,WeakMap 对象不可枚举。对于此集合,键引用为弱保存。如果要通过垃圾回收器来确定应用是否必须在内存中保留集合的每个成员,请使用 WeakMap。例如,对于缓存对象极大、你不希望在内存中不必要地保存对象的缓存方案,这会非常有用。在某些方案中,可以使用此对象防止内存泄漏。

以下示例演示如何使用 Map 对象。在此示例中,你使用 get 和 forEach 访问成员。 forEach 中的回调函数最多可包含三个参数,提供当前集合元素的值、当前元素的键和集合对象本身。

var m = new Map();m.set(1, "black");m.set(2, "red");m.set("colors", 2);m.set({x:1}, 3);document.write(m.get(2));document.write("<br />");m.forEach(function (value, key, mapObj) {    document.write(item.toString() + "<br />");});// Output:// red// black// red// 2// 3

使用 WeakMap 与使用 Map 类似,但只能使用 get 检索成员。有关示例,请参见 WeakMap 对象。

以下示例演示如何使用 Set 对象。在此示例中,回调函数包含一个参数,即当前集合元素的值。

var s = new Set();s.add("Thomas Jefferson");s.add(1776);s.add("founding father");s.forEach(function (value) {    document.write(item.toString() + ", ");});// Output:// Thomas Jefferson, 1776, founding father,

迭代器和生成器 (JavaScript)

迭代器是一个对象,用于将容器对象作为列表遍历。在 JavaScript 中,迭代器对象不是一个独立的内置对象,而是一个实现 next 方法以访问容器对象中的下一项的对象。

在 Microsoft Edge 中,可以创建自己的自定义迭代器。但是,使用生成器通常会更加方便,它可以极大程度地简化迭代器的创建。生成器是一种函数类型,该函数类型是迭代器的工厂。要使用生成器函数创建自定义迭代器,请参阅生成器。

生成器在 Microsoft Edge 启用了实验性 JavaScript 功能(关于:标志) 中受到支持。

迭代器

JavaScript 迭代器的实现涉及符合特定接口的两个或三个对象:

Iterable 接口Iterator 接口IteratorResult 接口

可以使用这些接口创建自定义迭代器。这让你能够使用 for…of 语句遍历可迭代对象。

Iterable 接口

Iterable 接口是可迭代对象(迭代器可以获得的对象)所需的接口。例如,for (let e of C) 中的 C 必须实现 Iterable 接口。

可迭代对象必须提供 Symbol.iterator 方法,该方法会返回一个迭代器。

obj[Symbol.iterator] = function() { return iterObj; }

此属性必须是不接受任何参数并返回一个符合 Iterator 接口的对象 (iterObject) 的函数。

许多内置类型(包括数组)现在已可迭代。 for…of 循环使用可迭代对象。(但是,并非所有内置可迭代对象都是迭代器。例如,Array 对象本身不是迭代器,但它是可迭代的,而 ArrayIterator 也是可迭代的。)

Iterator 接口

Symbol.iterator 方法返回的对象必须实现 next 方法。 next 方法具有以下语法。

iterObj.next() = function() { return iterResultObj; };

next 方法是会返回一个值的函数。该函数返回一个符合 IteratorResult 接口的对象 (iterResultObj)。如果对迭代器的 next 方法的之前调用返回 IteratorResult 对象(其 done 属性为 true),则迭代终止且不会再调用 next 方法。

迭代器还可能包括 return 方法,以确保脚本用完迭代器后正确处理该迭代器。

IteratorResult 接口

IteratorResult 接口是获得迭代器上 next 方法的结果所需的接口。 next 返回的对象必须提供 done 和 value 属性。

var iterResultObj = { done: true|false, value: value }

done 属性返回迭代器的 next 方法调用的状态,状态为 true 或 false。如果已达到迭代器的末尾,则 done 返回 true。如果未达到迭代器的末尾,则 done 返回 false,并有一个值可用。如果 done 属性(其自己的属性或继承的属性)不存在,则 done 的结果被视为 false。

如果 done 为 false,则 value 属性返回当前迭代元素值。如果 done 为 true,且如果提供了返回值,则这是迭代器的返回值。如果迭代器不具有返回值,则未定义 value。在这种情况下,如果符合对象没有继承显式值属性,则符合对象中可能不存在 value 属性。

生成器

要轻松创建和使用自定义迭代器,请搭配使用 function* 语法和一个或多个 yield 表达式以创建一个生成器函数。该生成器函数会返回一个迭代器(即生成器),该迭代器使生成器函数体能够执行。函数执行到下一条 yield 或 return 语句。

调用迭代器的 next 方法以从生成器函数返回下一个值。

下面的示例演示为字符串对象返回迭代器的生成器。

function* stringIter() {    var str = "bobsyouruncle";    var idx = 0;    while(idx < str.length)        yield str[idx++];}var si = stringIter();console.log(si.next().value);console.log(si.next().value);console.log(si.next().value);// Output:// b// o// b

在生成器中,yield 操作数表达式终止对 next 的调用并返回具有两个属性(done (done=false)value (value=operand))IteratorResult 对象。 operand 是可选的,如果保留为空缺,则其值未定义。

在生成器中,通过返回具有 done=trueIteratorResult 以及 value 属性的可选操作数结果,return 语句可以终止生成器。

还可以使用 yield* 表达式替代 yield,以委托到另一个生成器或另一个可迭代对象,例如数组或字符串。

如果将下面的代码追加到前面的示例中,则 yield* 委托到 stringIter 生成器。

function* strIter() {    yield "jo";    yield* stringIter();}var si2 = strIter();console.log(si2.next().value);console.log(si2.next().value);console.log(si2.next().value);console.log(si2.next().value);// Output:// jo// b// o// b

还可以将参数传递给 next 并使用该参数修改生成器的状态,以创建更高级的生成器。 next 将成为之前执行的 yield 表达式的结果值。在下面的示例中,当你将值 100 传递给 next 方法时,会重置生成器的内部索引值。

function* strIter() {    var str = "jobob";    var idx = 0;    while(idx , str.length) {        var modify = yield str[idx++];        if(modify == 100) {            idx = 0;        }    }var si3 = strIter();console.log(si2.next().value);console.log(si2.next().value);console.log(si2.next().value);console.log(si2.next(100).value);// Output:// j// o// b// j

其他高级生成器可能调用生成器的 throw 方法。引发的错误似乎会在生成器暂停的位置引发(在下一条 yield 语句之前)。


特殊字符 (JavaScript)

JavaScript 提供了可以包含在字符串中的转义序列,以创建不能直接键入的字符。

备注

字符串值是一个由零或多个 Unicode 字符(字母、数字和其他字符)组成的序列。 字符串括在成对的单引号或双引号内。 括在单引号内的字符串可包含双引号。 括在双号内的字符串中可包含单引号。

字符串中的每个字符均可由一个转义序列表示。 转义序列以反斜杠 () 开头,它通知 JavaScript 解释器下一个字符是特殊字符。

可以使用 \uhhhh 转义序列指定 Unicode 字符,其中 hhhh 是四位十六进制数。 Unicode 转义序列可以表示任何 16 位字符。 有关其他信息,请参阅 Unicode 码位转义序列。

可对某些字符使用单字符转义序列。 例如,\t 指定制表符。

转义序列

下表列举了一些常用字符的转义序列。

Unicode 字符值 转义序列 含义 类别 \u0008 \b Backspace \u0009 \t 制表符 空格 \u000A \n 换行 行结束符 \u000B \v 垂直制表符 空格 (参见此表后面的注释。) \u000C \f 换页 空格 \u000D \r 回车 行结束符 \u0020 空格 空格 \u0022 \” 双引号 (“) \u0027 \’ 单引号 (‘) \u005C \|反斜杠 () \u00A0 不间断空格 空格 \u2028 行分隔符 行结束符 \u2029 段落分隔符 行结束符 \uFEFF 字节顺序标记 空格

“类别”列指定字符是为空格还是行终止符。 trim 方法 (String) (JavaScript)从字符串删除前导空格、尾随空格和行终止符。

反斜杠本身用作转义字符。 因此,无法直接将其键入脚本。 如果想写入反斜杠,则必须键入两个反斜杠 (\)。

示例

说明
下面的示例阐释 \ 和 \’ 转义序列。
代码

document.write('The image path is C:\\webstuff\\mypage\\gifs\\garden.gif.');document.write ("<br />");document.write('The caption reads, "After the snow of \'97. Grandma\'s house is covered."');

Unicode 码位转义序列

在 Microsoft Edge 中,完全支持 Unicode。 最常见的 Unicode 码位点由四个十六进制数表示,如 /u0009 表示制表符。 Astral 码位(包括需要超过四个十六进制数的所有符号)现在支持采用简化格式。 通过使用“\u{码位}”格式,可以以文本格式表示完整的 Unicode 字符集。 例如,要表示符号 “��”,可以使用以下格式:“\u{20BB7}”。

在下面的代码示例中,字符串都是等效的。 (\uD842\uDFB7 是以前的版本中用于指定此符号的解决方法。)

"\u{20BB7}"=="��"=="\uD842\uDFB7"

RegExp 现在包括一个 /u 标志,用于启用对 astral 码位的完整支持。 例如,在下面的代码示例中,正则表达式中的 /u 标志允许匹配 astral 码位(句点匹配所提供的字符串中的任何字符)。

"��".match(/./u)[0].length == 2

/u 标志允许将新格式(\u{码位})分析为 Unicode 转义序列。 这是必需的,因为没有 /u 标志的 \u{xxxxx} 在正则表达式中具有不同的含义。
System_CAPS_note说明

对于 astral 码位,长度始终为 2。 这与以前版本中的行为一致。

String 对象现在包含支持 astral 码位的两个新方法,即 String.codePointAtString.fromCodePoint。 例如,可以使用 codePointAt 返回“��”符号的等效码位。

"��".codePointAt(0) == 0x20BB7

还可以使用 for…of 语句迭代码位。

for(var c of "��") {    console.log(c);}

模板字符串 (JavaScript)

在 Microsoft Edge 中,可以使用模板字符串来构造具有嵌入式表达式的字符串文本。模板字符串还为多行字符串提供内置支持。

若要构造模板字符串,请使用重读符号(也称为反引号)(‘) 替代单引号或双引号括起字符串。下面的代码示例演示一个简单的模板字符串。

Template strings can include 'single quotes' and "double quotes" inline.

模板字符串可以在无需使用换行符 (\n) 的情况下包含换行。

Template strings can include line breaks and don't need the linefeed character.

$ 字符用于指定模板字符串内的占位符。语法是 ${表达式},其中表达式是任意 JavaScript 表达式(如变量或函数),如以下示例中所示。

var name = "Bob";var str = `Hello ${name}, how are you this fine ${partOfDay()}?`console.log(str);function partOfDay () {    var hour = new Date().getHours();    if (hours <= 12) {        return “morning”;    } else if (hours <= 5) {        return “afternoon”;    } else {        return “evening”;    }}// Output:// Hello Bob, how are you this fine afternoon?

带标记的模板函数,它可以通过使用由模板字符串中参数调用的函数来修改此模板字符串的值。第一个参数是字符串文本的数组,由内含的模板字符串表达式分隔;第二个参数是包含模板字符串表达式的值的数组(Rest 参数)。

在以下示例中,带标记的模板函数 buildURL 用于构造 URL。此语法要使用后面紧跟模板字符串的函数名。

function buildURL(strArray, ...valArray) {    var newUrl = strArray[0] + "ja-ja" + "/" + valArray[1] +    "/" + valArray[2];    return newUrl;}var lang = "en-us";var a = "library";var b = "dn771551.aspx";// Call the tagged template function.var url = buildURL`http://msdn.microsoft.com/${lang}/${a}/${b}`;console.log(url);// Output:// http://msdn.microsoft.com/ja-ja/library/dn771551.aspx

如果需要访问传入的原始字符串值,则传递给带标记的模板函数的第一个参数支持可返回传入字符串的原始字符串形式的 raw 属性。

function buildURL(strArray, ...valArray) {    console.log(strArray.raw);}var lang = "en-us";var a = "library";var b = "dn771551.aspx";// Call the tagged template function.var url = buildURL`http://msdn.microsoft.com/${lang}/${a}/${b}`;// Ouput:// http://msdn.microsoft.com/// /// en-us// library

还可以使用 String.raw 函数返回模板字符串的原始字符串形式。


使用 bind 方法 (JavaScript)

JavaScript bind 方法具有几种用法。通常,它用于为在其他上下文中执行的函数保留执行上下文。 bind 创建具有与原始函数相同的主体的新函数。传递给 bind 的第一个参数指定绑定函数中的 this 关键字的值。也可以将其他可选参数传递到 bind。有关其他用法的示例,请参见 bind 方法 (Function) (JavaScript)。有关使用 bind 部分应用函数的示例,请参见 Hilo JavaScript 中的异步编程模式和提示(Windows 应用商店)。

使用 bind 保留执行上下文

通常,在添加事件侦听器时使用 bind 函数。在下面的代码示例中,bind 用于保留当前对象 (DataObject) 的上下文。通过使用 this 关键字将数据对象传递到 bind,这可在事件处理程序 (dataReadyHandler) 运行时提供对数据对象属性和函数的访问。为了阐释 bind 的工作原理,此代码会创建自定义事件。

var data;var dataReadyEvent = document.createEvent("Event");dataReadyEvent.initEvent("dataReady", true, false);function DataObject() {    this.name = "Data Object";    this.data = function () {        return data;    }    this.onDataCompleted = dataReadyHandler;    document.addEventListener('dataReady', this.onDataCompleted.bind(this));    // To see the result of not using bind, comment out the preceding line,     // and uncomment the following line of code.    // document.addEventListener('dataReady', this.onDataCompleted);}function dataReadyHandler() {    if (console && console.log) {        console.log("Data object property value: " + this.name);        console.log("Data object property value: " + this.data());    }}setTimeout(function () {    data = [0, 1, 2, 3];    document.dispatchEvent(dataReadyEvent);    }, 5000);}var dataObj = new DataObject();// Output:// Data Object// 0,1,2,3

如果注释掉使用 bind 的代码行,取消注释调用不带 bindaddEventListener 的代码行,然后重新运行此代码,则 dataReadyHandler 函数将失败。例如,在 dataReadyHander 中,this.name 将是未定义的,并且 this.data() 将导致发生错误,因为 this 对象不再引用此数据对象。


管理事件侦听器

如果 DOM 元素或对象的生存期不同于其关联事件侦听器的生存期,你可能需要使用 removeEventListener 方法来避免内存泄露。

事件侦听器和对象范围

下面的代码示例演示在调用 dataObjFactory() 函数时可能会导致内存泄露的代码。在此代码中,在每次创建新数据对象时,将为数据对象注册一个事件侦听器。为了使当前数据对象可用于 dataReady() 事件处理程序,在 addEventListener 中使用了 bind 方法 (Function) (JavaScript)。

 var data; var dataObj; var dataReadyEvent = document.createEvent("Event"); dataReadyEvent.initEvent("dataReady", true, false); function DataObject() {     this.name = "Data Object";     this.data = function () {         return data;     }     this.onDataCompleted = dataReady;     // this.handlerRef = this.onDataCompleted.bind(this);     // document.addEventListener('dataReady', this.handlerRef);     document.addEventListener('dataReady', this.onDataCompleted.bind(this)); } // Runs when the data is available. function dataReady() {     if (console && console.log) {         console.log("object value: " + this.name);         console.log("object value: " + this.data());     } }setTimeout(function () {    // Generate data after a timeout period.    data = [0, 1, 2, 3];    document.dispatchEvent(dataReadyEvent);}, 10000);function dataObjFactory() {     for (var x = 0; x < 100; x++) {         if (dataObj) {             // The following line of code has no effect.             document.removeEventListener('dataReady', dataObj.onDataCompleted);             dataObj = null;         }         dataObj = new DataObject();     } } dataObjFactory();

每个数据对象的侦听器均在 document 对象(该对象具有与数据对象不同的生存期)中注册。只要 document 对象仍保持在范围内,每个数据对象的已注册事件侦听器都会防止该对象被垃圾回收。(在某些现代 JavaScript 设计模式中,文档对象在 Web 应用的生存期内将保留在范围中。)为了防止内存泄露,将在 dataObjFactory 函数中调用 removeEventListener。但是,由于 removeEventListener 尚未在 bind 函数返回的事件处理程序的绑定版本上调用,此代码失败。

要修复此代码并使数据对象可供垃圾回收,你必须先存储一个对事件处理程序绑定版本的引用(如此代码中所示),然后将存储的引用传递到 addEventListener。下面是 DataObject 的更正后代码:

function DataObject() {    this.name = "Data Object";    this.data = function () {        return data;    }    this.onDataCompleted = dataReady;    this.handlerRef = this.onDataCompleted.bind(this);    document.addEventListener('dataReady', this.handlerRef);    // document.addEventListener('dataReady', this.onDataCompleted.bind(this));}

最后,你需要在绑定函数存储的引用 (handlerRef) 上调用 removeEventListener。下面是 dataObjFactory 的更正后代码:

function dataObjFactory() {     for (var x = 0; x < 100; x++) {         if (dataObj) {             document.removeEventListener('dataReady', dataObj.handlerRef);         }         dataObj = new DataObject();     } }

现在,对 removeEventListener 调用有效,并且不需要的数据对象可以进行垃圾回收,即使 document 对象仍在范围中也是如此。


脚本疑难解答 (JavaScript)

任何编程语言都具有惊人之处。 例如,JavaScript 中的 null 值与 C 或 C++ 语言中的 Null 值的行为不同。

以下是您编写 JavaScript 脚本时可能遇到的一些存在麻烦的方面。

语法错误

在编写脚本时注意细节很重要。 例如,字符串必须在引号内。

脚本解释的顺序

JavaScript 解释是 Web 浏览器的 HTML 分析过程的一部分。 如果在文档中将脚本置于 <HEAD> 标记内,则会先解释该脚本,然后再解释 <BODY> 标记的任何部分。 如果具有在 <BODY> 标记中创建的对象,则这些对象在分析 <HEAD> 时不存在,并且脚本不能对这些对象进行操作。

此行为是 Internet Explorer 所特有的。 ASP 和 WSH 具有不同的执行模型(像其他主机一样)。

自动类型强制

JavaScript 是带有自动强制功能的松散类型化语言。 尽管具有不同类型的值不全等,下面的示例中的表达式的计算结果也为 true

"100" == 100;false == 0;

若要检查类型和值是否均相同,请使用全等运算符 (===)。 以下两个表达式的计算结果均为 false:

"100" === 100;false === 0;

运算符优先级

运算符优先级确定在计算表达式的过程中执行操作的时间。 在下面的示例中,即使表达式中首先出现减法运算符,也会先计算乘法,再计算减法。

theRadius = aPerimeterPoint - theCenterpoint * theCorrectionFactor;

将 for…in 循环用于对象

在使用 for…in 循环访问对象的属性时,无法预测或控制将对象字段赋给循环计数器变量的顺序。 此外,在不同的语言实现中,顺序可能会有所不同。

with 关键字

虽然 with 语句为访问已存在于指定对象中的属性带来了方便,但无法用来向对象添加属性。 若要在对象中创建新的属性,必须明确地引用该对象。

this 关键字

虽然您在对象定义中使用 this 关键字来引用对象本身,但在当前执行的函数不是对象定义时,您无法使用 this 或类似的关键字来引用该函数。 如果将函数作为方法赋给对象,则可以在函数中使用 this 关键字来引用该对象。

编写在 Internet Explorer 中编写脚本的脚本

当解释器遇到 </SCRIPT> 标记时,该标记将终止当前脚本。 若要显示“</SCRIPT>”本身,请将其重新书写为至少两个字符串(例如“</SCR”“IPT>”),随后可以在写出这两个字符串的语句中将它们串联在一起。

Internet Explorer 中的隐式窗口引用

因为可以一次性打开多个窗口,所以任何隐式窗口引用均指向当前窗口。 对于其他窗口,则必须使用显式引用。


条件编译 (JavaScript)

利用条件编译,可以使用新的 JavaScript 语言功能,同时又保留与不支持这些功能的旧版本之间的兼容性。

语句

可通过使用 @cc_on 语句或者使用 @if@set 语句来激活条件编译。 条件编译的一些典型用途包括在 JavaScript 中使用新功能、将调试支持嵌入到脚本中以及跟踪代码执行。

始终将条件编译代码放置在注释中,以便不支持条件编译的主机(如 Netscape Navigator)将其忽略。 这是一个示例。

/*@cc_on @*//*@if (@_jscript_version >= 4)    alert("JavaScript version 4 or better");    @else @*/    alert("Conditional compilation not supported by this scripting engine.");/*@end @*/

此示例使用特殊的注释分隔符,仅在 @cc_on 语句激活条件编译后使用这些分隔符。 不支持条件编译的脚本引擎仅看到表明不支持条件编译的消息。


条件编译变量 (JavaScript)

以下预定义变量可用于条件编译。 如果变量不为 true,则该变量是未定义的,并且在被访问时其行为与 NaN 相同。

变量

变量 说明 @_win32 如果在 Win32 系统上运行,则为 true。 @_win16 如果在 Win16 系统上运行,则为 true。 @_mac 如果在 Apple Macintosh 系统上运行,则为 true。 @_alpha 如果在 DEC Alpha 处理器上运行,则为 true。 @_x86 如果在 Intel 处理器上运行,则为 true。 @_mc680x0 如果在 Motorola 680x0 处理器上运行,则为 true。 @_PowerPC 如果在 Motorola PowerPC 处理器上运行,则为 true。 @_jscript 始终为 true。 @_jscript_build 包含 JavaScript 脚本引擎的生成号。 @_jscript_version 包含 major.minor 格式的 JavaScript 版本号。

严格模式 (JavaScript)

严格模式是一种将更好的错误检查引入代码中的方法。在使用严格模式时,你无法使用隐式声明的变量、将值赋给只读属性或将属性添加到不可扩展的对象等。本主题后面的代码在严格模式下受到的限制部分列出了相关限制。有关严格模式的更多信息,请参见 ECMAScript 语言规范版本 5。

声明严格模式

可以通过在文件、程序或函数的开头添加 “use strict”; 来声明严格模式。此类声明称作“指令序言”。严格模式声明的范围取决于其上下文。如果在全局上下文(函数的范围之外)中声明严格模式,则程序中的所有代码都处于严格模式。如果在函数中声明严格模式,则函数中的所有代码都处于严格模式。例如,在以下示例中,所有代码都处于严格模式,并且函数外部的变量声明会导致出现语法错误“严格模式下未定义变量”。

"use strict";function testFunction(){    var testvar = 4;    return testvar;}// This causes a syntax error.testvar = 5;

在以下示例中,仅 testFunction 中的代码处于严格模式。函数外部的变量声明不会导致语法错误,但函数内部的声明会导致语法错误。

function testFunction(){    "use strict";    // This causes a syntax error.    testvar = 4;    return testvar;}testvar = 5;

代码在严格模式下受到的限制

下表列出了严格模式下适用的最重要的限制。

语言元素 限制 错误 示例 变量 使用变量但不声明。 SCRIPT5042:严格模式下未定义变量 JavaScript testvar = 4; 只读属性 写入到只读属性。 SCRIPT5045:严格模式下不允许分配到只读属性 JavaScript var testObj = Object.defineProperties({}, { prop1: { value: 10, writable: false // by default }, prop2: { get: function () { } } }); testObj.prop1 = 20; testObj.prop2 = 30; 不可扩展的属性 将属性添加到 extensible 属性设置为 false 的对象。 SCRIPT5046:无法为不可扩展的对象创建属性 JavaScript var testObj = new Object(); Object.preventExtensions(testObj); testObj.name = “Bob”; delete 删除变量、函数或参数。 SCRIPT1045:严格模式下不允许对 <表达式> 调用 Delete JavaScript 删除 configurable 特性设置为 false 的属性。 var testvar = 15; function testFunc() {}; delete testvar; delete testFunc; Object.defineProperty(testObj, “testvar”, { value: 10, configurable: false }); delete testObj.testvar; 重复属性 在一个对象文本中多次定义某个属性。 SCRIPT1046:严格模式下不允许一个属性有多个定义 JavaScript var testObj = { prop1: 10, prop2: 15, prop1: 20 }; 重复参数名 在一个函数中多次使用某个参数名。 SCRIPT1038:严格模式下不允许正式参数名称重复 JavaScript function testFunc(param1, param1) { return 1; }; 未来保留关键字 将未来保留关键字用作变量或函数名。 SCRIPT1050:无法使用标识符的未来保留字。严格模式下将保留标识符名称。 implements interface package private protected public static yield 八进制数 对数值文本分配八进制值,或尝试对八进制值使用转义。 SCRIPT1039:严格模式下不允许使用八进制数字参数和转义字符 JavaScript var testoctal = 010; var testescape = \010; this 当 this 的值为 null 或 undefined 时,该值不会转换为全局对象。 JavaScript function testFunc() { return this; } var testvar = testFunc(); 在非严格模式下,testvar 的值为全局对象,但在严格模式下,该值为 undefined。 作为标识符的 eval 字符串“eval”不能用作标识符(变量或函数名、参数名等)。 JavaScript var eval = 10; 语句或块中声明的函数 无法在语句或块中声明函数。 SCRIPT1047:在严格模式下,函数声明无法嵌套在语句或块中。它们只能显示在顶级或直接显示在函数体中。 JScript var arr = [1, 2, 3, 4, 5]; var index = null; for (index in arr) { function myFunc() {}; } eval 函数内声明的变量 如果在 eval 函数内声明变量,则不能在此函数外部使用该变量。 SCRIPT1041:严格模式下“eval”用法无效 JavaScript eval(“var testvar = 10”); testvar = 15; 虽然允许间接计算,但你仍无法使用在 eval 函数外部声明的变量。 JavaScript var indirectEval = eval; indirectEval(“var testvar = 10;”); document.write(testVar); 此代码会导致错误 SCRIPT5009:“testVar”未定义。 作为标识符的 Arguments 字符串“arguments”不能用作标识符(变量或函数名、参数名等)。 SCRIPT1042:严格模式下“arguments”用法无效 JavaScript var arguments = 10; 函数内的 arguments 无法更改本地 arguments 对象的成员的值。 JavaScript function testArgs(oneArg) { arguments[0] = 20; } 在非严格模式下,可以通过更改 arguments[0] 的值来更改 oneArg 参数的值,从而使 oneArg 和 arguments[0] 的值都为 20。在严格模式下,更改 arguments[0] 的值不会影响 oneArg 的值,因为 arguments 对象只是一个本地副本。 arguments.callee 不允许。 JavaScript function (testInt) { if (testInt– == 0) return; arguments.callee(testInt–); } with 不允许。 SCRIPT1037:严格模式下不允许使用“with”语句 JavaScript with (Math){ x = cos(3); y = tan(7); }
原创粉丝点击