ECMA-262 把对象定义为:'无序属性的集合,其属性可以包含基本值,对象或者函数'。(参考资料javascript高级程序设计)
对象特殊属性:数据属性和访问器属性
1)数据属性:
[Configurable]-是否可删除 [Enumerable]-是否可枚举for in [Writable]-是否可写 [value]值
要修改默认属性必须使用defineProperty(Object,key,descriptor)方法
例如:
var Person = {
name:"john",
age:"20",
job:"student",
sayName: function(){
alert(this.name);
}
}
Object.defineProperty(Person,"age",{
configurable: false,
enumerable: false,
writable: false,
value: 28,
})
console.log(Person.age);//28
console.log(delete(Person.age));//不可删 false
console.log(Person.age=20);
Prson.age = 20;
console.log(Person.age)//28,只读
定义多个属性 definePropertys(object,{
age:{
value:23
},
name:{
configurable:false
}
});
2)访问器属性:不包含数据,在读取时调用geter函数,写入时调用seter函数,该属性必须用defineProperty方法定义
如:
Object.defineProperty(Person,'name',{
get:function(){
return this.name;
},
set:function(){
console.log("修改");
}
});
Person.name = "Li";//修改
读取特性:Object.getOwnPropertyDescriptor(object,"property")(..还好不常用);
*重点来了:*
1)创建对象
工厂模式:
function Person(name,age){
var Object = new Object();
Object.name = name;
Object.age = age;
Object.sayName = function(){
console.log(this.name);
}
return Object;
}
var p1 =new Person("许涛",32);
构造函数模式:
var Person = function(name,age){
this.name = name;
this.age = age;
this.sayName = function(){
console.log(this.name);
}
}
var p1 = new Person(name,age);
构造函数模式缺点:对象方法创建太多了影响性能,因为每个对象创建时都new
了一个方法
原型模式:
var Person = function(){};
Person.prototype.name = "马云";
Person.prototype.age = 11;
Person.prototype.sayName = function(){
console.log(this.name);
}
简写:
Person.prototype = {
name:"马云",
age:12,
sayName: function(){
console.log(this.name);
}
}
var p1 = new Person();
原型模式缺点,每个对象实例属性一样
例如:
Person.prototype.friends =["许涛","马云","张三"];
var p2 = new Person();
//这里在p2实例中加了
p2.friends.push("John");
console.log(p1.friends);//["许涛","马云","张三","John"]
所以组合使用构造函数模式与原型模式可以有效避免缺点,集二者之长(使用最多):
function Person(name,age){
//这里使用构造函数模式定义属性
this.name = name;
this.age = age;
this.friends = ["John","Li"];
}
//把方法写在原型链中,所有实例共享
Person.prototype = {
sayName: function(){
console.log("this.name");
}
}
var p1 =new Person("peter",32);
var p2 = new Person("安琪",18);
p2.friends.push("peter");
console.log(p1.friends);//['john','li'];
console.log(p2.friends);//[...'peter'];
还有其他自定义模式都是基于前三种模式进化出来的。。
2)继承
原型链继承:
function Person(){
this.type = "man";
}
Person.prototype.sayType = function(){
console.log("my name is: "+this.type)
}
//子对象
function Student(){
this.job = "student";
}
//继承
Student.prototype =new Person();
var xiaoming = new Student();
console.log(xiaoming.type);
缺点:属性共享问题
Person.prototype.hairs =["black","green","yellow"];
var stu1 = new Student();
var stu2 = new Student();
stu2.hairs.push("blue");
console.log(stu1.hairs,stu2.hairs);
//构造函数继承:
//子对象
function Chinese(){
//继承 通过call调用Person方法
Person.call(this);
this.country = "China";
}
var c1 = new Chinese();
console.log(c1.type);//man
//组合继承:(常用)
//这里新创建一个People对象作为父对象
function People(name){
this.name = name;
}
People.prototype.sayName = function(){
console.log(this.name);
return this.name;
}
//子对象
function Man(name){
People.call(this,name);
}
Man.prototype = new People();
Man.prototype.constructor = Man;
var man1 = new Man();
console.log(man1.name);
console.log(man1.sayName());
//缺点:无论何时都要调用两次父类
//原型式继承
//这里定义一个object方法用作原型继承返回一个子实例
function object(SuperObject){
function F(){};
F.prototype = SuperObject;
return new F();
}//es5 新增Object.create()方法与object()方法一样
//寄生式继承 相当于对object进行扩展
function clone(o){
var clone = object(o);
//添加新方法
clone.sayHi = fuction(){
alert("Hi");
}
return clone;
}
//寄生组合式继承
function iher(subType,superType){
var prototype = object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
//实例
function SuperType(name){
this.name = name;
}
SuperType.prototype.sayName = function(){
console.log(this.name);
}
//子对象
function SubType(name,age){
SuperType.call(this,name);
this.age = age;
}
//不用两次调用父类了
iher(SubType,SuperType);