码迷,mamicode.com
首页 > 其他好文 > 详细

面向对象

时间:2015-03-28 17:04:31      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:

function factorial(num){
    if(num<=1){
        return 1;
    }else{
        return num = num * factorial(num-1);
    }
}
改进
function factorial(num){
    if(num<=1){
        return 1;
    }else{
        return num = num * arguments.callee(num-1);
    }
}

var factorial = function f(num){
    if(num<=1){
        return 1;
    }else{
        return num = num * f(num-1);
    }
}

有权访问私有变量和私有函数的公有方法称为特权方法
function person(name){
    this.getName = function () {
        return name;
    }
    this.setName = function (value) {
        name = value;
    }
在构造函数中定义特权方法必须使用构造函数模式来实现这个目的
缺点 针对每个实例都会创建同样一组新方法

静态私有变量实现特权方法
(function(){
    var name = "";
    Person = function (value) {
        name = value;
    }
    Person.prototype.getName = function () {
        return name;
    }
    Person.prototype.setName = function (value) {
        name = value;
    }
})()
使用原型增进了代码复用 但是每个实例都没有自己的私有变量

模块模式 为单例创建私有变量和特权方法
var singleton = function () {
    //私有变量和函数 
    var components = new Array();
    //初始化
    components.push(new BaseComponents);
    //公共
    return {
        getComponentCount : function(){
            return components.length;
        }
        registerComponent : function(component){
            if(typeof component =="object"){
                components.push(component);
            }
        }

    }
} ();

增强模块模式 适用于单例必须是某种类型的实例
var application = function () {
    //私有变量和函数 
    var components = new Array();
    //初始化
    components.push(new BaseComponent());
    
    //创建application的一个局部副本
    var app = new BaseComponent();
    //公共
    app.getComponentCount = function(){
        return components.length;
    }
    app.registerComponent = function(component){
        if(typeof component =="object"){
            components.push(component);
        }
    }
    return app;
}(); 

创建对象
工厂模式
function createPerson(name, age, job){
    var o = new object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
        alert(this.name);
    }
    return o;
}
构造函数模式
function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
        alert(this.name);
    }
    //等价于 this.sayName = new Function ("alert(this.name)");
}
Person大写开头 
构造函数意味着将来可以把它的实例标识为一种特定的类型
缺点:每个方法都要在每个实例上重新创建一遍

原型模式
function Person(){
    Person.prototype.name = name;
    Person.prototype.age = age;
    Person.prototype.job = job;
    Person.prototype.sayName = function(){
        alert(this.name);
    }
}
[[prototype]]   __proto__  isPrototypeOf()  es5 Object.getPrototypeOf(0)
这个指针链接存在于实例和构造函数的原型对象之间
 function hasPrototypeProperty(object, name){
     return !object.hasOwnProperty(name) && (name in object);
 }

 for in 返回所有能偶通过对象访问的 可枚举的属性 
 ie早期bug     屏蔽不可枚举属性的实例属性不会出现在for in  ex:toString()

 取得对象上所有可枚举的实例属性 
 Object.keys()

 取得所有实例属性 无论是否可枚举 Object.getOwnPropertyNames()  ex:constructor

function Person(){}
    
Person.prototype = {
    //constructor :Person, 但是其[[Enumerable]]为true 默认是false的
    name : "zz",
    age : 25,
    job : "Software Engineer"
    sayName : function(){
        alert(this.name);
    }
}
注意: var friend = new Person();  friend.constructor == Object 因为重写了默认的prototype对象

可以修改原生对象的原型 但是不建议 可能导致命名冲突 也可能意外的重写了原生方法

问题·:原型模式省略了为构造函数传递初始化参数,结果所有实例在默认情况下取得相同的值
对于包含引用类型值得属性就会出问题 相互影响 如数组

组合模式 构造函数和原型
function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["aa","bb"];  //放在原型中就出现上面问题
}
Person.prototype = {
    constructor :Person,
    this.sayName = function(){
        alert(this.name);
}

动态原型
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);
        }
    }
}
这里对原型的修改立即会在所有实例中得到反应
动态原型 不能使用对象字面量重写原型 重写会切断指针联系

寄生构造函数模式
function Person(name, age, job){
    var o = new object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
        alert(this.name);
    }
    return o;
}
特殊情况下用来为对象创建构造函数,如创建一个具有额外方法的特殊数组
返回的对象和构造函数或者构造函数的原型没有关系 不能依赖instanceof 一般不建议使用

稳妥构造函数模式
function Person(name, age, job){
    var o = new object();
    o.sayName = function(){
        alert(name);
    }
    return o;
}
安全环境适用 不引用this 不用new操作符调用
除了sayName 没有办法再访问到name

继承
原型链 终点Object.prototype
instanceof isPrototype()
子类定义方法或重写超类方法一定要放在替换原型语句后
即:SubType.prototype = new SuperType();之后
不要使用字面量创建原型方法
一样存在引用值共享 无法向超类传递参数的问题

借用构造函数
function SuperType(name){
    this.name = name;
}
function subType(){
    //继承了SuperType 同时传递了参数
    SuperType.call(this, "zz");

    this.age = 25;
}
仅构造函数无法避免方法都在构造函数中定义了 无法函数复用

组合继承
function SuperType(name){
    this.name = name;
    this.colors = ["red","blue"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
}
function SubType(){
    //继承了SuperType 
    SuperType.call(this, name);  //第二次
    this.age = 25;
}
//继承方法
SubType.prototype = new SuperType(); //第一次
//创建子方法
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
    alert(this.age);
}
无论什么情况下都会调用两次超类构造函数 不得不在调用子类型构造函数时重写这些属性

原型式继承
function object(o){
  function F(){};
  F.prototype = o;
  return new F();
}
本质上object()对传入的o完成了一次浅复制 前提必须有一个对象可以作为另一个对象的基础
ES5 Object.create()方法规范原型式继承 
两个参数 一个用做新对象原型的对象 一个为新对象定义额外属性的对象
一样有引用类型值问题

寄生式继承
function createAnother(original){
    var clone = object(original);
    //以某种方式来增强这个对象
    clone.sayHi = function(){
        alert("hi");
    }
    return clone;
}
主要考虑对象而不是自定义类型和构造函数下适用
不能复用

寄生组合式继承
解决组合继承调用两次超类构造函数(第二次调用产生的属性屏蔽了第一次调用原型中的同名属性)
不必为了指定子类型的原型而调用超类型的构造函数 所需的无非是超类型原型的副本
function inheritPrototype(subType, superType){
    var prototype = object(superType.prototype);
    //弥补重写原型而失去的默认constructor属性
    prototype.constructor = subType;
    subType.prototype = prototype;
}
unction SuperType(name){
    this.name = name;
    this.colors = ["red","blue"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
}
function SubType(){
    SuperType.call(this, name);  
    this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
    alert(this.age);
}
只调用了一次SuperType 避免了在SubType.prototype上创建不必要、多余的属性
同时原型链保持不变 正常使用instanceof isPrototype()
YUI的YAHOO.lang.extend() 采用了

 

面向对象

标签:

原文地址:http://www.cnblogs.com/bgstyle/p/4374329.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!