• ECMAScript5 严格模式 JSON 还有更多


    ECMAScript5 规范自推出以来, 对javascript的发展产生了蛮大的影响。这篇文章是我翻译自John Resig(jQuery作者)的一篇博文

    《ECMAScript 5 Strict Mode, JSON, and More》

    之前我分析了ES5的对象和属性系统。这是这门语言的一大亮点。

    同样有许多其他新特性和API也需要我们注意。最主要的有严格模式(Strict Mode)和原生JSON支持(native JSON support)。

    严格模式(Strict Mode)

    严格模式在ES5中是个新特性,它允许你在一个“严格”的环境中执行你的代码。严格的环境会阻止采用一些特定的代码行为,抛出更多的异常(总体上说给用户更多的信息和规范编码)。

    自ES5对ES3进行兼容后,所有在ES3中可以正常使用,但在ES5中注为“不推荐”的特性将在严格模式下失效(或者抛出异常)。

    严格模式将以如下这些方式推进代码规范:

    • 捕获一些常见的代码漏洞,抛出异常

    • 当一些相对“不安全”的代码被执行时,进行阻止或抛出异常(例如获取全局对象访问)

    • 禁掉那些令人疑惑或者欠考虑的特性

    大多数关于严格模式的信息可以在ES5规范[PDF]223页找到。

    应该注意的是ES5的严格模式与FireFox提供的严格模式不同(可以通过about:config来启动javascript.options.strict)。ES5关注编码规范上的潜在错误。(而FireFox的严格模式只是强调一些最佳实践)。

    如何启动严格模式?

    很简单。在你的代码前加上"use strict",为你所有代码启动严格模式:

    "use strict";
    

    或者只在一个执行上下文内,如:

    function imStrict() {
    	"use strict";
    	// ... your code...
    }
    

    看吧,启动严格模式的语法,不能再简单了,就一条语句"use strict"就行了。没有新的语法,不需要什么复杂的配置,并且对老的浏览器也没什么副作用。

    ES5并没有对语言语法进行添加或者更改。所以可以在老浏览器中进行优雅降级。

    在一个函数中定义严格模式,你可以在其中定义自己的javascript库,而不影响外部的代码。

    // Non-strict code...
    (function() {
    	"use strict";
    	
    	// Define your library strictly...
    })();
    // Non-strict code...
    

    当前很多库用上面的这种包裹技术(把整个库包在一个自动执行的匿名函数中)。

    那么当你把脚本置于严格模式后,会发生什么呢?很多事情

    变量和属性

    尝试赋值foo = 'bar';如果'foo'没有事先定义,那么将失败。在这之前,foo会被赋值,并且foo会作为全局对象window的属性window.foo,现在这会抛出异常。确保避免一些恼人的bug。

    对任何writable属性(attribute)为false的属性(property)进行写操作,configurable属性(attribute)为false的属性(property)进行删除操作,extensible属性(attribute)为false的对象进行添加属性(property)都会导致报错。传统上,当尝试这些行为时错误不会被抛出,将静静地失败。

    删除变量,一个函数,一个参数将导致错误。

    var foo = "test";
    function test() {}
    
    delete foo;   // Error
    delete test;  // Error
    
    function test2(arg) {
    	delete arg;       // Error           
    }
    

    在一个字面对象中不止一次定义一个同名属性,将导致异常抛出

    // Error
    { foo: true, foo: false }
    

    eval

    几乎任何尝试使用'eval'这个名称的操作都会被禁止.

    // All generate errors...
    obj.eval = ...
    obj.foo = eval;
    var eval = ...;
    for(var eval in ...) {}
    function eval() {}
    function test(eval) {}
    function(eval) {}
    new Function("eval")
    

    除此之外,通过eval引入的新变量无效

    eval("var a = false;");
    print(typeof a); // undefined
    

    Functions

    试图去覆写arguments对象将导致出错:

    arguments = [...]; // now allowed
    

    定义同名的参数会导致错误:function(foo, foo)

    对arguments.caller和arguments.callee的访问将抛出异常。因此任何你想引用的匿名函数要给个名称,像这样:

    setTimeout(function later() {
    	// do stuff...
    	setTimeout(later, 1000);
    }, 1000);
    

    其他函数的arguments和caller属性不在存在,并且定义它们的能力被禁止:

    function test() {
    	function inner() {
    		// Don't exist, either
    		test.arguments = ...; // Error
    		inner.caller = ...; // Error
    	}
    }
    

    最后一个长期困扰的(并且很恼人的)bug被解决了:像如下用例中,null或者undefined被强制转换为全局对象。严格模式现在阻止这样的事情发生,并会抛个异常。

    (function() { ... }).call(null); // Exception
    

    with

    with语句在严格模式中完全被干掉了,事实上它的出现会作为语法错误。

    ES5严格模式对代码的改变是多样的。观察开发者如何开始采用这些规范和它如何改变javascript开发,将是个有趣的过程。

    JSON

    ECMAScript语言第二个主要的特性是加入了对JSON的原生支持。

    我已经拥护此项推进很久了,如今我很高兴的看到它被写入了规范。

    有2个主要的方法用于处理JSON:JSON.parse(把一个JSON字符串转成一个javascript对象)和JSON.stringify(把一个javascript对象转成一个序列化的字符串)。

    JSON.parse(text)

    把一个序列化的JSON字符串转成一个javascript对象。

    var obj = JSON.parse('{"name": "John"}');
    // Prints 'John'
    print(obj.name);
    

    JSON.parse(text, translate)

    使用一个转换函数 转换值或者进行移除

    function translate(key, value) {
    	if( key === "name") {
    		return value + " Resig";
    	}
    }
    
    var obj = JSON.parse('{"name": "John", "last": "Resig"}', translate);
    // Prints 'John Resig'
    print( obj.name );
    
    // Undefined
    print( obj.last );
    

    JSON.stringify(obj)

    把一个对象转成一个序列化的JSON字符串

    var str = JSON.stringify({name: "John"});
    // Prints {"name": "John"}
    print( str );
    

    JSON.stringify(obj, ["white", "list"])

    只序列化白名单指定的属性

    var list = ["name"];
    var str = JSON.stringify({name: "John", last: "Resig"}, list);
    // Prints {"name": "John"}
    print( str );
    

    JSON.stringify(obj, translate)

    用转换函数来序列化对象

    function translate(key, value) {
    	if(key === "name") {
    		return value + " Resig";
    	}
    }
    
    var str = JSON.stringify({"name": "John", "last": "Resig"}, translate);
    // Prints {"name": "John Resig"}
    print( str );
    

    JSON.stringify(obj, null, 2)

    给输出增加指定的空格数

    var str = JSON.stringify({ name: "John" }, null, 2);
    // prints
    // {
    //	 "name": "John"
    // }
    print( str );
    

    JSON.stringify(obj, null, "\t")

    使用特定的字符来做分隔

    var str = JSON.stringify({ name: "John" }, null, "\t");
    // Prints:
    // {\n\t"name": "John"\n}
    print( str );
    

    另外,一些基础类型添加了新的通用方法,但是,恕我直言,它们并不有趣。来自String,Boolean和Number的结果等同于调用valueOf(), Date的结果等同于调用toISOString()

    // Yawn
    String.prototype.toJSON
    Boolean.prototype.toJSON
    Number.prototype.toJSON
    Date.prototype.toJSON
    

    .bind()

    内置bind()方法的引入很受欢迎,它可以使一个函数的执行环境得到改变(几乎等同于prototype framework中的bind实现)

    Function.prototype.bind(thisArg, arg1, arg2...)
    

    使得函数的this关键字指向一个特定的对象,并传入任何你要指定的参数。

    var obj = {
    	method: function(name) {
    		this.name = name;
    	}
    };
    
    setTimeout(obj.method.bind(obj, "John"), 100);
    

    Date

    首先,如果所给的值是ISO格式,Date构造函数会试图去解析该日期,接着再处理它接受的其他输入。

    var date = new Date("2009-05-21T16:06:05.000Z");
    
    // Prints 2009-05-21T16:06:05.000Z
    print( date.toISOString() );
    

    另外,date对象现在有个新的toISOString()方法,以ISO格式输出日期

    .trim()

    一个原生,内置的trim()方法被String对象支持,和我们自己实现的trim方法功能一样,但是原生的效率更高。

    Array

    JavaScript Array扩展方法包括: indexOf, lastIndexOf, every, some, forEach, map, filter, reduce 和 reduceRight

    另外一个新方法Array.isArray(译者注:可以理解为Array的static方法)被包含了进来, 提供和下面这段代码同样地功能:

    Array.isArray = function( array ) {
    	return Object.prototype.toString.call( array ) === "[object Array]";
    }
    
  • 相关阅读:
    [NOI Online 2022 提高组] 如何正确地排序
    SP10707 COT2 Count on a tree II
    葡萄牙报表配置Mysql ODBC
    开发小笔记
    时隔几年,决定把日常笔记记录下来
    电脑软件专用名称
    docker exec进入容器的原理
    云原生监控体系建设
    [rust学习] 一、rust的核心概念与总结
    接口
  • 原文地址:https://www.cnblogs.com/AndyWithPassion/p/ES5_StrictMode_JSON.html
Copyright © 2020-2023  润新知