第三章 字面量和构造函数
对象字面量
//开始定义一个空对象var dog = {};//向dog对象添加一个属性dog.name = "Benji";//现在,向dog对象添加一个方法dog.getName = function () { return dog.name;}console.log(dog.getName);console.log(dog.getName());dog.getName = function () { //重新定义该返回方法 //返回一个硬编码的值 return "Lilu";}console.log(dog);console.log(dog.getName);console.log(dog.getName());delete dog.name; //删除属性console.log(dog);//添加更多的方法和属性 dog.say = function () { return "Woof!";};dog.fleas=true;console.log(dog);
//即使最简单的{}对象也具有从Object.prototype继承的属性和方法if(typeof Object.prototype.clone==="undefined"){ Object.prototype.clone=function(){ alert('克隆'); };}var dog={};console.log(dog);dog.clone()
对象字面量语法
来自构造函数的对象
可以使用自己的构造函数,或使用一些类似Object(),Date(),String()的内置构造函数创建对象
//第一种方法 使用字面量 var car={goes:"far"}; console.log(car); //另一种方法 使用内置构造函数 var car2=new Object(); car2.goes="far"; console.log(car2); //另一种方法 使用内置构造函数 var car3=new String(); car3.goes="far"; console.log(car3); var car4=new Date(); car4.goes="far"; console.log(car4);
对象构造函数捕捉
不要使用new Object构造函数,应该使用简单可靠的对象字面量模式。
//警告:前面的反模式 //一个空对象 var o=new Object(); console.log(o.constructor); console.log(o.constructor===Object); //true; //一个数值对象 var o=new Object(1); console.log(o.constructor===Number); //true; console.log(o.toFixed(2)); // 1.00 //一个字符串对象 var o=new Object("I am string"); console.log(o.constructor===String); //true; //一般的对象并没有substring()方法, //但是字符串对象都有该方法 console.log(typeof o.substring); //function //一个布尔对象 var o=new Object(true); console.log(o.constructor===Boolean);//true;
自定义构造函数
//Person构造函数的定义var Person = function (name) { this.name = name; this.say = function (){ return "I am " + this.name; };};var lilu=new Person("Lilu");lilu.say(); //输出为I am Liluconsole.log(lilu);console.log(lilu.say());
代码改进
//Person构造函数的定义var Person = function (name) { this.name = name; };Person.prototype.say=function(){ return "I am "+this.name;}var lilu=new Person("Lilu");lilu.say(); //输出为I am Liluconsole.log(lilu);console.log(lilu.say());
可重用的成员,比如可重用方法都应该放置到对象的原型中。
构造函数的返回值
构造函数将隐式返回this,甚至在函数中没有显式的加入return语句。
var Objectmaker=function(){ this.name="haha";};var o=new Objectmaker();console.log(o.name) // 输出为 And that's that
但构造函数中可以自由的返回任意对象,只要它是一个对象。
var Objectmaker=function(){ //下面的name属性将被忽略 //这是因为构造函数决定改为返回另一个对象 this.name="This is it"; //创建并返回一个新对象 var that={}; that.name="And that's that"; return that;};var o=new Objectmaker();console.log(o.name) // 输出为 And that's that
强制使用new模式
构造函数仍然只是函数,只不过它以new的方式调用。
忘记使用new操作符会导致构造函数中的this指向全局对象。
//构造函数function Waffle(){ this.tastes="yummy";}//定义一个新对象var good_morning=new Waffle();console.log(typeof good_morning); //objectconsole.log(good_morning.tastes); //yummy//反模式 //方剂使用new操作符var good_morning=Waffle();console.log(typeof morning); //将输出undefinedconsole.log(window.tastes); //将输出yummy
命名约定
构造函数名称中首字母大写,普通函数和方法的名称中的首字母变成小写
使用that
function Waffle(){ var that={}; that.tastes="yummy"; return that;}var good_morning=Waffle();console.log(typeof good_morning);console.log(good_morning.tastes);
对于简单对象,甚至不需要用类似that这样的局部变量
function Waffle(){ return { tastes:"yummy" }; }var good_morning=Waffle();console.log(typeof good_morning);console.log(good_morning.tastes);
这种模式(忘记写new)的问题在于它会丢失到原型的链接,任何您添加到Waffle()原型的成员,对象都是不可用的。
自调用构造函数
function Waffle(){ if(!(this instanceof Waffle)){ return new Waffle(); } this.tastes="yummy"; } Waffle.prototype.wantAnother=true; var first=Waffle(); var second=new Waffle(); console.log(first.tastes); //输出yummy console.log(second.tastes); //输出yummy
数组字面量
//具有三个元素的数组//警告:反模式var a=new Array("itsy","bitsy","spider");//完全相同的数组var a=["itsy","bitsy","spider"];console.log(typeof a); //输出object,这是由于数组本身也是对象类型console.log(a.constructor===Array); //输出true
数组字面量语法
数组字面量表示法 (Array literal notation)
数组构造函数的特殊性
当向Array()构造函数传递单个数字时,它设置了数组的长度,但干数组中并没有实际的元素。
//具有一个元素的数组var a=[3];console.log(a.length); //1console.log(a[0]); //3//具有三个元素的数组var a =new Array(3);console.log(a.length); //3console.log(typeof a[0]);//输出undefined
向该构造函数传递一个浮点数,情况变得更加糟糕。
//使用数组字面量var a=[3.14];console.log(a[0]); //3.14var a=new Array(3.14); //输出RangeError:invalid array length(范围错误,不合法的数组长度)console.log(typeof a); //输出undefined
尽量避免使用Array()构造函数,坚持使用数组字面量。
某些情况下使用Array()构造函数 比如返回一个具有255个空白字符的字符串 var white=new Array(256).join(' ');
检查数组性质
ECMAScript5定义了一个新的方法Array.isArray()检测数组性质
Array.isArray([]); //true//试图以一个类似数组的对象欺骗检查Array.isArray({ length:1, "0":1, slice:function(){}}); //false
向下兼容的写法
if(typeof Array.isArray==-"undefined"){ Array.isArray=function(arg){ return Object.prototype.toString.call(arg)==="[object Array]"; };}
JSON
JSON与文字对象之间唯一的语法差异在于,在JSON中,属性名称需要包装在引号中才能成为合法的JSON.
而在对象字面量中,仅当属性名称不是有效的标识符时]才会需要引号。 如{"first name":"lilu"}
使用JSON
使用JSON.parse()方法解析字符串安全性更好。
//一个输入JSON字符串var jstr='{"mykey":"my value"}';//反模式var data=eval('('+jstr+')');//优先使用的方法var data=JSON.parse(jstr);console.log(data.mykey); // my value
在YUI3库里使用自带方法
//一个输入JSON字符串var jstr='{"mykey":"my value"}';//解析该字符串,并且使用一个YUI实例YUI().use('json-parse',function(Y){ var data=Y.JSON.parse(jstr); console.log(data.mykey); //myvalue});
在jQuery中存在一个parseJSON()方法
//一个输入JSON字符串var jstr='{"mykey":"my value"}';var data=jQuery.parseJSON(jstr);console.log(data.mykey);
JSON.stringify()可以序列化对象或数组为一个JSON字符串
var dog={ name:"Fido", dob:new Date(), legs:[1,2,3,4]};var jsonstr=JSON.stringify(dog);console.log(jsonstr);
正则表达式字面量
正则表达是也是对象
- 使用new RegExp()构造函数
- 使用正则表达式字面量 (优先原则字面量模式)
//正则表达式字面量var re=/\\/gm;//构造函数var re=new RegExp("\\\\","gm");console.log(re);
正则表达式字面量语法
- g-全局匹配
- m-多行
- i-大小写敏感
var re=/pattern/gmi
调用类似String.prototype.replace()的方法
var no_letters="abc123XYZ".replace(/[a-z]/gi,"");console.log(no_letters); //输出123
function getRE(){ var re=/[a-z]/; re.foo="bar"; return re;}var reg=getRE();var re2=getRE();console.log(reg===re2); //reg.foo="baz";console.log(re2.foo); //
调用RegExp()使用new和不使用new的行为是相同的。
错误对象
try{ throw{ name:"MyErrorType", message:"oops", extra:"This was rather embarrassing", remedy:genericErrorHandler };}catch(e){ alert(e.message);}