天天看點

JavaScript模式 讀書筆記二第三章 字面量和構造函數

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);           

複制

//即使最簡單的{}對象也具有從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);
}           

複制