第三章 字面量和構造函數
對象字面量
//開始定義一個空對象
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 Lilu
console.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 Lilu
console.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); //object
console.log(good_morning.tastes); //yummy
//反模式
//方劑使用new操作符
var good_morning=Waffle();
console.log(typeof morning); //将輸出undefined
console.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); //1
console.log(a[0]); //3
//具有三個元素的數組
var a =new Array(3);
console.log(a.length); //3
console.log(typeof a[0]);//輸出undefined
複制
向該構造函數傳遞一個浮點數,情況變得更加糟糕。
//使用數組字面量
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()檢測數組性質
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);
}
複制