在js中,一切皆对象
工厂模型
function createPerson(name , sex , age){
var obj = new Object();
obj.name = name ;
obj.sex = sex ;
obj.age = age ;
obj.sayName = function(){
alert(this.name);
}
return obj;
}
var p1 = createPerson('z3' , '男' , 20);
var p2 = createPerson('z4' , '女' , 25);
alert(p1.sex);
p1.sayName();
构造函数式
// 函数的第一个字母大写 (类的模版)
function Person(name , age , sex){
this.name = name ;
this.age = age ;
this.sex = sex ;
this.sayName = function(){
alert(this.name);
}
}
var p1 = new Person('小1' , 20 , '男');
// 在另一个对象的作用域中调用
var o = new Object();
Person.call(o,'小4' , 12 , '女');
alert(o.name);
原型
原型对象里的所有属性和方法 被所有构造函数实例化出来的对象所共享
每次代码读取一个对象的属性的时候: 首先会进行一次搜索:搜索实例对象里的属性,,如果没有,再去对应的原型对象里去搜索属性 如果有就返回 没有返回undefined
isPrototypeOf(new instance) //判断原型的方法
ECMA5: Object.getPrototypeOf() //根据实例对象获得原型对象
hasOwnProperty('name') //判断是否是实例属性
function Person(){
}
Person.prototype.name = 'z3';
Person.prototype.age = 20 ;
Person.prototype.sayName = function(){alert('我是原型对象的方法!')};
var p1 = new Person();
alert(p1.name); // z3
var prototypeObj = Object.getPrototypeOf(p1);//根据实例对象获得原型对象
alert(prototypeObj == Person.prototype);
// in 操作符 判断属性是否存在于 实例对象和原型对象中
// 在原型对象中 是否存在这个属性 第一个参数:当前对象 ,第二个参数:要判断的属性
function hasPrototypeProperty(object , name){
return !object.hasOwnProperty(name) && name in object ;
}
// ECMA5新特性 Object.keys(): 拿到当前对象里的所有keys 返回一个数组
var p1 = new Person();
p1.name = 'z3';
p1.age = 20 ;
var attributes = Object.keys(p1);
alert(attributes);
var attributes2 = Object.keys(Person.prototype);
alert(attributes2);
// ECMA5 constructor属性: 该属性是不能被枚举的[eable = false]
// Object.getOwnPropertyNames 枚举对象所有的属性 :不管该内部属性能否被枚举
var attributes3 = Object.getOwnPropertyNames(Person.prototype);
alert(attributes3);
简单原型
function Person(){
}
Person.prototype = {
name: 'z3',
age : 20,
job : '程序员',
say : function(){
alert('我是原型的函数!');
}
};
// ECMA5 给原型对象重新设置构造器的方法 Object.defineProperty(); // FF4+ ie8+
// 参数1 :重设构造器的对象 参数2:设置什么属性 参数3:options配置项
Object.defineProperty(Person.prototype , 'constructor' , {
enumerable : false ,
value : Person
});
var p1 = new Person(); // 注意简单原型使用的顺序(实例对象必须在原型对象之后创建)
alert(Person.prototype.constructor); // Person
// 枚举对象的keys
for( attr in p1){
alert(attr);
}
组合使用原型和构造函数式
开发时常用的方式
//属性都放到类里
function Person(name , age , friends , job){
this.name = name ;
this.age = age ;
this.friends = friends ;
this.job = job ;
}
//方法都放到原型
Person.prototype = {
constructor: Person ,
sayName : function(){
alert(this.name);
}
};
动态原型模式
function Person(name , age , friends , job){
this.name = name ;
this.age = age ;
this.friends = friends ;
this.job = job ;
//动态原型方法:
if( typeof this.sayName != 'function'){
Person.prototype.sayName = function(){
alert(this.name);
}
}
}
稳妥构造函数式
- 没有公共属性
- 不能使用this对象
function Person(name , age , job){
// 创建一个要返回的对象
var obj = new Object();
var name = name ;
obj.sayName = function(){
alert(name);
}
return obj ;
}
原型继承
特点:即继承了父类的模版,又继承父类的原型对象
缺点:……
// 父类
function Person(name, age){
this.name = name ;
this.age = age ;
}
Person.prototype.id = 10 ;
// 子类
function Boy(sex){
this.sex = sex ;
}
//继承
Boy.prototype = new Person('z3');
var b = new Boy();
alert(b.name);
alert(b.id);
构造函数继承(类继承)
只继承模版,不继承原型对象
// 父类
function Person(name, age){
this.name = name ;
this.age = age ;
}
Person.prototype.id = 10 ;
// 子类
function Boy(name , age , sex){
Person.call(this,name,age);
this.sex = sex;
}
var b = new Boy('张三' , 20 , '男');
alert(b.name);
alert(b.sex);
alert(b.id); //父类的原型对象并没有继承
混合继承
原型继承+借用构造函数继承
缺点:继承了父类的2次模版
// 父类
function Person(name, age){
this.name = name ;
this.age = age ;
}
Person.prototype.id = 10 ;
Person.prototype.sayName = function(){alert(this.name);};
// 子类
function Boy(name , age , sex){
Person.call(this,name,age); // 借用构造函数继承父类的模版
this.sex = sex ;
}
// 原型继承
Boy.prototype = new Person(); //继承父类的模版和原型对象
var b = new Boy('李四' , 20 , '男');
alert(b.name);
alert(b.sex);
b.sayName();
混合继承改进
//继承1次父类的模版 继承一次父类的原型对象
function extend(sub ,sup){
// 目的:实现只继承父类的原型对象
var F = new Function(); // 创建一个空函数 目的:空函数进行中转
F.prototype = sup.prototype; // 实现空函数的原型对象和超类的原型对象转换
sub.prototype = new F(); // 原型继承
sub.prototype.constructor = sub ; // 还原子类的构造器
//保存父类的原型对象: 一方面方便解耦 另一方面方便获得父类的原型对象
sub.superClass = sup.prototype; //自定义一个子类的静态属性 接受父类的原型对象
//判断父类的原型对象的构造器(加保险)
if(sup.prototype.constructor == Object.prototype.constructor){
sup.prototype.constructor = sup ;
}
}
//父类
function Person( name , age){
this.name = name ;
this.age = age ;
}
Person.prototype = {
constructor: Person ,
sayHello: function(){
alert('hello world!');
}
};
//子类
function Boy(name , age , sex){
//借用构造函数继承 只复制了父类的模版
Boy.superClass.constructor.call(this , name , age);
this.sex = sex ;
}
extend(Boy , Person);
// 给子类加了一个 原型对象的方法
Boy.prototype.sayHello = function(){
alert('hi javascript!');
}