第三章 字面量和构造函数
对象字面量
代码语言:javascript复制//开始定义一个空对象
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);
代码语言:javascript复制//即使最简单的{}对象也具有从Object.prototype继承的属性和方法
if(typeof Object.prototype.clone==="undefined"){
Object.prototype.clone=function(){
alert('克隆');
};
}
var dog={};
console.log(dog);
dog.clone()
对象字面量语法
来自构造函数的对象
可以使用自己的构造函数,或使用一些类似Object(),Date(),String()的内置构造函数创建对象
代码语言:javascript复制//第一种方法 使用字面量
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构造函数,应该使用简单可靠的对象字面量模式。
代码语言:javascript复制//警告:前面的反模式
//一个空对象
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;
自定义构造函数
代码语言:javascript复制//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 Lilu
console.log(lilu);
console.log(lilu.say());
代码改进
代码语言:javascript复制//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 Lilu
console.log(lilu);
console.log(lilu.say());
可重用的成员,比如可重用方法都应该放置到对象的原型中。
构造函数的返回值
构造函数将隐式返回this,甚至在函数中没有显式的加入return语句。
代码语言:javascript复制var Objectmaker=function(){
this.name="haha";
};
var o=new Objectmaker();
console.log(o.name) // 输出为 And that's that
但构造函数中可以自由的返回任意对象,只要它是一个对象。
代码语言:javascript复制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指向全局对象。
代码语言:javascript复制//构造函数
function Waffle(){
this.tastes="yummy";
}
//定义一个新对象
var good_morning=new Waffle();
console.log(typeof good_morning); //object
console.log(good_morning.tastes); //yummy
//反模式
//方剂使用new操作符
var good_morning=Waffle();
console.log(typeof morning); //将输出undefined
console.log(window.tastes); //将输出yummy
命名约定
构造函数名称中首字母大写,普通函数和方法的名称中的首字母变成小写
使用that
代码语言:javascript复制function Waffle(){
var that={};
that.tastes="yummy";
return that;
}
var good_morning=Waffle();
console.log(typeof good_morning);
console.log(good_morning.tastes);
对于简单对象,甚至不需要用类似that这样的局部变量
代码语言:javascript复制function Waffle(){
return {
tastes:"yummy"
};
}
var good_morning=Waffle();
console.log(typeof good_morning);
console.log(good_morning.tastes);
这种模式(忘记写new)的问题在于它会丢失到原型的链接,任何您添加到Waffle()原型的成员,对象都是不可用的。
自调用构造函数
代码语言:javascript复制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
数组字面量
代码语言:javascript复制//具有三个元素的数组
//警告:反模式
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()构造函数传递单个数字时,它设置了数组的长度,但干数组中并没有实际的元素。
代码语言:javascript复制//具有一个元素的数组
var a=[3];
console.log(a.length); //1
console.log(a[0]); //3
//具有三个元素的数组
var a =new Array(3);
console.log(a.length); //3
console.log(typeof a[0]);//输出undefined
向该构造函数传递一个浮点数,情况变得更加糟糕。
代码语言:javascript复制//使用数组字面量
var a=[3.14];
console.log(a[0]); //3.14
var 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()检测数组性质
代码语言:javascript复制Array.isArray([]); //true
//试图以一个类似数组的对象欺骗检查
Array.isArray({
length:1,
"0":1,
slice:function(){}
}); //false
向下兼容的写法
代码语言:javascript复制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()方法解析字符串安全性更好。
代码语言:javascript复制//一个输入JSON字符串
var jstr='{"mykey":"my value"}';
//反模式
var data=eval('(' jstr ')');
//优先使用的方法
var data=JSON.parse(jstr);
console.log(data.mykey); // my value
在YUI3库里使用自带方法
代码语言:javascript复制//一个输入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()方法
代码语言:javascript复制//一个输入JSON字符串
var jstr='{"mykey":"my value"}';
var data=jQuery.parseJSON(jstr);
console.log(data.mykey);
JSON.stringify()可以序列化对象或数组为一个JSON字符串
代码语言:javascript复制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()的方法
代码语言:javascript复制var no_letters="abc123XYZ".replace(/[a-z]/gi,"");
console.log(no_letters); //输出123
代码语言:javascript复制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的行为是相同的。
错误对象
代码语言:javascript复制try{
throw{
name:"MyErrorType",
message:"oops",
extra:"This was rather embarrassing",
remedy:genericErrorHandler
};
}catch(e){
alert(e.message);
}