js中的oop编程

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

稳妥构造函数式

  1. 没有公共属性
  2. 不能使用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!');
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值