天天看點

JavaScript進階程式設計第六章

ECMAScript有兩種屬性:資料屬性和通路器屬性

修改對象的屬性的特性

var person = {};

Object.defineProperty(person,“name”,{

writeable:false,

value:“lala”

});

alert(person.name); //lala

person.name = “haha”;

alert(person.name); //lala

這個是無法修改name的值

var person = {};

Object.defineProperty(person,“name”,{

configurable:false,

value:“lala”

});

alert(person.name); //lala

delete person.name;

alert(person.name); //lala

通路器屬性

例子:

var book = {

year :2018,

edition :1

};

Object.defineProperty(book,“year”,{

get:function(){

return this.year;

},

set:function(newValue){

this.year = newValue;

this.edition += newValue-2019;

}

});

book.year = 2020;

alert(book.edition); //2

隻指定getter意味着屬性不能寫

隻指定setter,意味着屬性不能讀

定義多個屬性:

例子:

var book = {};

Object.defindProperty(book,{

year :{

value:2020

},

edition:{
	value:1
},

year:{set:funtion(newValue){
	this.year = newValue
},
	
          get:funtion(){
	return this.year;
}
}
           

});

把資料屬性和通路器屬性一起定義了

工廠模式,由于JavaScript沒有類的定義,那麼實作這個工廠模式是定義一個方法

function createPerson(name,age,job){

var obj = new Object();
obj.name = name;
obj.age = age;
obj.job = job;
obj.sayName = function(){
	alert(this.name);
	         };
return obj;
           

};

person1 = create(“lala”,18,“engineer”);

或者這樣

function Person(name,age,job){

this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
	alert(this.name);
	         };
           

};//沒有newObjct,沒有return,使用this

var person2 = new Person(“haha”,20,“engineer”);

按照慣例,構造函數的名字開頭是大寫的

任何函數,用new來調用,那麼它就是構造函數,隻要不是用new來調用的,那麼它就是普通函數

另一種方式來構造對象

fiction Person(name,age,job){

this.name = name;

this.age = age;

this.job = job;

this.sayName = function(){

alert(this.name);

};

};

var o = new Object();

Person.call(o,“lala”,20,“engineer”);

每個函數都有一個prototype屬性,這個屬性是一個指針,指向一個對象

原型對象(共享屬性和方法):

function Person(){}

Person.prototype.name = “lala”;

Person.prototype.age = 18;

Person.prototype.sayName = function(){

alert(this.name);

};

var person1 = new Person();

var person2 = new Person();

alert(person1.sayName == person2.sayName); //true

無論什麼時候,隻要建立一個新函數,就會為這個函數建立一個prototype屬性,這個屬性指向函數的原型對象

每當代碼讀取某個對象的屬性,首先會檢視對象執行個體本身有沒有給定名字的屬性,如果有就用了,沒有就繼續搜素指針指向的原型對象

var person = {};

function Person(){}

Person.prototype.name = “lala”;

Person.prototype.age = 18;

Person.prototype.sayName = function (){alert(this.name);};

var person1 = new Person();

person1.name = “haha”;

alert(person1.name); //haha

alert(person1.hasOwnProperty(“name”); //true,因為person1有自己的name屬性,如果沒有會傳回false,通過這個 //方法可以很清楚知道,現在通路的這個屬性是執行個體屬性還是原型屬性

in 的使用

var person = {};

function Person(){}

Person.prototype.name = “lala”;

Person.prototype.age = 18;

Person.prototype.sayName = function (){alert(this.name);};

var person1 = new Person();

alert(“name” in person1); //true

原型中的toString函數是不可枚舉的

使用keys方法擷取可枚舉屬性的字元串數組

var person = {};

function Person(){}

Person.prototype.name = “lala”;

Person.prototype.age = 18;

Person.prototype.sayName = function (){alert(this.name);};

var keys = Object.keys(Person.prototype); //注意這裡如果寫成Person是不行的

var person1 = new Person();

person1.name = “haha”;

person1.age = 20;

var key1 = Object.keys(person1); //注意這裡如果寫成person1.prototype是不行的

更常見的封裝是

function Person() = {}

Person.prototype = {

name :"lala",
age :18,
sayName: function(){
alert(this.name);
}
           

};

var person = new Person();

alert(person.name); //lala

但是如果這樣寫

function Person(){}

var person = new Person();

Person.prototype = {

name :“lala”,

age :18

};

alert(person.name); //undefind

留給讀者思考prototype指針,上面這種寫法的prototype指針發生了變化

通過原生對象的原型,不僅可以用所有預設的方法,還有為它增加新的方法

例子:

String.prototype.startWith = function(text){

return String.indexOf(text) == 0;

};

var mas = “hello world”;

alert(mas.startWith(“h”); //true

我們一般都會使用混合模式來建立對象,既使用構造函數,也使用原型模式

例子:

function Person(name,age,job){

this.name = name;
this.age = age;
this.job = job;
           

}

Person.prototype.sayName = function(){

alert(this.name);
           

};

var person1 = new Person(“lala”,20,“engineer”);

var person2 = new Person(“haha”,20,“engineer”);

person1.sayName();

person2.sayName();

對13點的方法進行部分改造

function Person(name,age,job){

this.name = name;
this.age = age;
this.job = job;

if(typeof this.sayName != "function"){
Person.prototype.sayName = function(){
	alert(this.name);
}
}
           

}

var person1 = new Person(“lala”,20,“engineer”);

var person2 = new Person(“haha”,20,“engineer”);

person1.sayName();

person2.sayName();

重溫一下call和apply方法

apply:方法能劫持另外一個對象的方法,繼承另外一個對象的屬性.

Function.apply(obj,args)方法能接收兩個參數

obj:這個對象将代替Function類裡this對象

args:這個是數組,它将作為參數傳給Function(args–>arguments)

call:和apply的意思一樣,隻不過是參數清單不一樣.

Function.call(obj,[param1[,param2[,…[,paramN]]]])

obj:這個對象将代替Function類裡this對象

params:這個是一個參數清單

分析: Person.apply(this,arguments);

this:在建立對象在這個時候代表的是student

arguments:是一個數組,也就是[“zhangsan”,”21”,”一年級”];

也就是通俗一點講就是:用student去執行Person這個類裡面的内容,在Person這個類裡面存在this.name等之類的語句,這樣就将屬性建立到了student對象裡面

利用apply可以幹很多事情:

例如:

求最大值的Math.max(裡面隻能傳n個參數,不能傳入數組)

但是這樣寫可以傳入數組

var getMax = Math.max.apply(null,array);