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