Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

javascript设计模式学习(一) #1

Open
molychnCHN opened this issue Mar 23, 2017 · 0 comments
Open

javascript设计模式学习(一) #1

molychnCHN opened this issue Mar 23, 2017 · 0 comments

Comments

@molychnCHN
Copy link
Owner

在目前的前端开发模式过程中,一直以来都以面向过程为主,没有仔细考虑到过程中代码的性能优化,这对产品迭代及后续的javascript开发带来一定影响,毕竟完全以面向过程为主,按照产品需求去实现页面交互不能更高效提高自己的javascript编程水平。

javascript面向对象编程基础

采用对象收编变量来防止团队开发过程中的变量冲突,避免定义的相同方法覆盖掉原有功能。
在收编的过程中,可以在对象中返回(return)属性或者方法,实现属性与方法的复制。

var MethodsObject = function(){
    return {
        method: function(){
            //do some thing
        }
        //...
    }
}
//实现方法复制
var a = MethodsObject();
a.method();

这种模式在开发过程中也可以使用类来实现方法复制。通过this的指向创建(new)新的对象。

var MethodsObject = function(){
    this.method = function(){}
    //...
}
var a = new MethodsObject();
a.method();

使用类复制对象方法与属性的过程中,在每次创建(new)的过程中,对一些共有的方法会造成比较高的消耗,所以我们也将共有方法放置在对象原型(prototype)中。

var MethodsObject = function(){}
//type1
MethodsObject.prototype = {
    method: function(){}
    //...
}
//type2
MethodsObject.prototype.method = function(){}

在每个方法实现的过程中可以返回对象本身实现方法链式引用

var MethodsObject = function(){
    method1: function(){
        return this;
    },
    method2: function(){
        return this;
    }
}
MethodsObject.method1().method2();

在原生对象Function中添加方法(在团队开发过程中不采用此方式,防止函数污染)

Function.prototype.addMethod = function(name, fn){
    this[name] = fn;
    return this;
}

面向对象变成就是将需求抽象成一个对象,然后针对这个对象分析其特征(属性)与动作(方法)。也称之为类。
其中通过this定义的属性或者方法是该对象自身拥有的,所以每次通过类创建一个新对象时,this指向的属性与方法会得到相应的创建,而通过prototype继承的属性与方法是每个对象通过prototype访问到,这些属性与方法并不随着新对象创建而再次创建。
在每个prototype对象中会生成一个constructor属性指向拥有整个原型对象的函数或对象。

继承
继承的基本原理在于声明父类与子类,同时将父类的实例赋值给子类的原型
类的原型对象的作用就是为类的原型添加共有方法,但类不能直接访问这些属性和方法,需要通过prototype来访问。通过实例化父类,子类复制了父类的属性与方法,并将原型__proto__指向了父类的原型,这样在可以访问父类构造函数中的属性和方法外,同时拥有了父类原型上的属性与方法。
但是这样的继承会共用父类的"引用"类型,间接影响了其他继承该父类的其他子类数据,而且因为子类实现继承是靠原型prototype对父类的实例化实现的,所以在创建父类时,无法向父类传递参数,也就无法在实例化父类的时候对父类构造函数的属性进行初始化。
针对此除了这种模式的继承外,可以在子类中通过.call()方法实现继承

//声明子类
function SubClass(arg){
    //继承父类
    SuperClass.call(this, arg)
}

.call()可以更改函数的作用环境,子类调用此方法将子类中的变量在父类中执行
因此可以结合两者的优点进行组合继承,在子类构造器中执行父类构造函数(call),在子类原型上实例化父类

//原型式继承
function inheritObject(o){
    //声明一个过渡函数对象
    function F(){}
    //过渡对象的原型继承父对象
    F.prototype = o;
    //返回过渡对象的一个实例
    return new F();
}

原型式集成跟类式继承一样,将父类构造函数的属性与方法复制,同时"引用"类型的属性被共用

//寄生式继承
function create(obj){
    //通过原型继承方式创建新对象
    var o = new inheritObject(obj);
    //扩展新对象
    o.method = function(){
        //do some thing
    }
    //返回扩展后新对象
    return o;
}

在原型式继承的基础上进行二次封装,并且对继承的对象进行扩展

//寄生式组合继承
function inheritPrototype(subClass, superClass){
    //复制一份父类的原型副本保存在变量中
    var p = inheritObject(superClass.prototype);
    //修正因为重写子类导致子类的constructor属性被修改
    p.constructor = subClass;
    //设置子类的原型
    subClass.prototype = p;
}

//使用组合继承会造成子类不是父类的实例,而子类的原型是父类的实例

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant