《JavaScript 模式》读书笔记(3)— 字面量和构造函数3
这是字面量和构造函数的最后一篇内容,其中包括了JSON、正则表达式字面量,基本值类型包装器等知识点。也是十分重要的哦。
五、JSON
JSON是指JavaScript对象表示以及数据传输格式。它是一种轻量级数据交换格式,且可以很方便地用于多种语言,尤其是在JavaScript中。实际上,对于JSON而言,只是一个数组和对象字面量表示方法的组合:
{"name":"value","some":[1,2,3]}
JSON和文字对象之间唯一的区别,就是在JSON中,属性名称需要包装在引号中才能成为合法的JSON。而在对象字面量中,仅当属性名称不是有效的标识符时才会需要引号,比如:字符之间有空格{"first name":""Dave}。
此外,JSON字符串中,不能使用函数或正则表达式字面量。
使用JSON
注意,并不推荐盲目使用eval()对任意JSON字符串进行求值,其原因在于安全性的影响。如果使用JSON.parse()方法解析字符串,其安全性会更好。
// 一个输入JSON字符串 var jstr = '{"name":"value","some":[1,2,3]}'; // 反模式 var data = eval('(' + jstr + ')'); // 优先使用的方法 var data = JSON.parse(jstr); console.log(data.name); // value
与JSON.parse()相对的方法是JSON.stringify()。它可以将任意的对象或数组序列化为一个JSON字符串。
var dog = { name:'Fido', dob:new Date(), legs:[1,2,3,4] }; var jsonstr = JSON.stringify(dog);
六、正则表达式字面量
JavaScript中的正则表达式也是对象,可以用两种方法创建:
1、使用new RegExp()构造函数。
2、使用正则表达式字面量。
// 正则表达式字面量 var re = /\\/gm; // 构造函数 var re = new RegExp('\\\\','gm');
正如上面的代码,字面量表示法更加简短,并且不需要使用“类”的构造函数方式思考。优先选择字面量表示法创建正则表达式。
此外,在使用构造函数时,不仅需要转义引号,还需要双反斜杠。如上代码,这里需要四个反斜杠才能匹配单个反斜杠。使得其难以阅读和修改。
正则表达式字面量语法
正则表达式字面量表示法使用了斜杠(分隔号“/”)来包装用于匹配的正则表达式模式。在第二个斜杠之后,可以将该模式修改为不加引号的字母形式:
- g——全局匹配
- m——多行
- i——大小写敏感匹配
模式修改器可以允许任何顺序或者组合方式出现:var re = /pattern/gmi;
还有一个要注意的是,在ES5之前,字面量在解析时只有一次创建了一个对象。也就是说,如果在一个循环中创建了相同的正则表达式,那么后面返回的对象与前面创建的对象相同,并且所有的属性都将被设置为第一次的值。这种行为已经在ES5中得到了改变,并且字面量会创建新的对象。
最后要说明的是,调用RegExp()时不使用new的行为与使用new的行为时相同的。
七、基本值类型包装器
JavaScript有五个基本的值类型:数字、字符串、布尔、null和undefined。除了null和undefined以外,其他三个具有所谓的基本包装对象。可以使用内置构造函数Number(),String()和Boolean()创建包装对象。
为了说明基本(primitive)数字和数字对象(object)之间的差异,请看:
// 一个基本数值 var n = 100; console.log(typeof n);//输出"number" // 一个数值Number对象 var nobj = new Number(100); console.log(typeof nobj);// 输出"object"
包装对象包含了一些有用的属性和方法。比如,数字对象具有形如toFixed()和toExponential()的方法。字符串对象具有substring()、charAt()、toLowerCase()等方法以及length属性。与基本值类型相比较而言,这些包装对象的方法用起来十分方便,这也是用这种方法创建对象的一个很好的理由。但是这些方法在基本值类型上也能够起作用。只要调用这些方法,基本值类型就可以在后台被临时转换为一个对象,并且表现的犹如一个对象。
// 用来作为对象基本字符串 var s = "hello"; console.log(s.toUpperCase());// "HELLO" // 值本身可以作为一个对象 "monkey".slice(3,6); // "key" // 与数值的方法相同 (22 / 7).toPrecision(3); // "3.14"
由于基本值类型也可以充当对象,只要需要它们这样做,不过通常并没有理由去使用更为冗长的包装构造函数。很显然,比如当可以简单地使用“hi”时,就不必编写“new String("hi");”这样冗长的语句。
// 避免使用以下结构: var s = new String("my string"); var n = new Number(101); var b = new Boolean(true); // 更好且更加简单的语句 var s = "my string"; var n = 101; var b = true;
通常使用包装对象的原因之一是您有扩充值以及持久保存状态的需要。这是由于基本值类型并不是对象,他们不可能扩充属性。
// 基本字符串 var greet = "Hello there"; // 为了使用split()方法,基本数据类型被转换成对象 greet.split(' ')[0]; // "Hello" // 试图增加一个原始数据类型并不会导致错误 greet.smile = true; // 但是它并不会实际运行 typeof greet.smile; // "undefined"
上面的代码中,greet只能被临时转换成对象,以使得该方法/属性可以访问,且运行时不会产生错误。另一个方面,如果使用new String()来定义一个对象greet,那么对其扩充的smile属性将会按照预期运行。扩充一个字符串、数字或布尔值的情况比较少见,除非这种行为就是您所需要的,否则可能并不需要包装构造函数。
当使用时没有带new操作符时,包装构造函数将传递给它们的参数转换成一个基本类型值:
typeof Number(1);// 输出“number” typeof Number("1");// 输出“number” typeof Number(new Number());// 输出“number” typeof String(1);// 输出“string” typeof Boolean(1);// 输出“boolean”
八、错误对象
JavaScript中有一些内置错误构造函数(error constructor),比如Error()、SyntaxError()、TypeError()以及其他,这些错误构造函数都带有throw语句。通过这些错误构造函数创建的错误对象具有下列属性:
- name:用于创建对象的构造函数的名称属性。它可以是一般的“Error”或者更为专门的构造函数,比如“RangeError”。
- message:当创建对象时传递给构造函数的字符串。
错误对象也还有一些其他的属性,比如发生错误的行号和文件名,但这些额外属性都是浏览器扩展属性,在多个浏览器实现中并不一致,因而并不可靠。
另一方面,throw适用于任何对象,并不一定是由某个错误构造函数所创建的对象,因此可以选择抛出自己的对象:
function genericErrorHandler() { console.log("错误处理中....") } try { throw { name: "MyErrortype",//自定义错误类型 message: "oops", extra: "This is rather embarrassing", remedy: genericErrorHandler // 指定应该处理该错误的函数 }; } catch (e) { // 通知用户 alert(e.message);//输出"oops" // 优美的处理错误 e.remedy(); // 调用函数genericErrorHandler() }
错误构造函数以函数的形式调用(不带new)时,其表现行为与构造函数(带new)相同,并且返回同一个错误对象。
我们这篇文章整体的内容就结束了,我们主要学习了对象字面量、数组字面量、正则表达式字面量、以及构造函数和new、还有一些其他的内置构造函数比如不建议使用的String()、Number()、Boolean()等,此外还讨论了多种不同的Error()构造函数。
注意:在一般情况下,除了Date()构造函数,很少需要使用其他内置构造函数。
本文来自博客园,作者:Zaking,转载请注明原文链接:https://www.cnblogs.com/zaking/p/12560128.html