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