zoukankan      html  css  js  c++  java
  • 慎用prototype={...}

    >
    慎用prototype={...}

        在网上见过很多人创建JavaScript类时喜欢将所有的实例方法都以上下文(Context)的方式赋值给对象的prototype属性:

    function Obj() {
        this.prop1 = 'prop1'; // instance property
        this.prop2 = 'prop2';
    }
    Obj.staticProp = 'Static Prop';
    Obj.staticMethod = function () {
        // do some static behavior
    };
    Obj.prototype = {
        method1: function() {
            // do somthing
        },
        method2: function() {
            // do somthing
        }
    };

    这样做看起来使创建类的代码更加简洁明了,但是内部隐藏着不少可能出现的问题。如你所见到,Obj.prototype = {...}这
    条语句是用上下文(即{}匿名对象)把对象的prototype属性完完全全地覆盖掉,这意味着以前prototype生来具有的一些内部方
    法现在都不存在了
    。而这也就是出现问题的地方。举一个例子,假如你想利用上述方法创建对象,但是你还想很集中地定义类
    的静态属性和方法,进而考虑利用对象的constructor函数属性来向创建对象的类追加方法(注意,这个例子的思路可能会产生
    问题,比如我们想不创建实例的情况下直接使用静态方法或属性等,但是请记住,这只是一个为了说明上述代码创建对象可能会
    产生的潜在问题,与本例的易用性无关。),那么你的代码可能会是这样:
    function Obj() {
        this.prop1 = 'prop1'; 
    // instance property
        this.prop2 = 'prop2';
        
        this._init();
    }
    Obj.prototype = {
        _init: 
    function () {
            _init: 
    function () {
            this.constructor.staticProp = '
    Static Prop';
            this.constructor.staticMethod = 
    function () {
                    
    // do some static behavior
            };
        },
        method1: 
    function() {
            
    // do somthing
        },
        method2: 
    function() {
            
    // do somthing
        }
    };

    但是你会发现这段代码根本就不起作用,类Obj并没有获得任何的静态属性或方法。这是怎么回事呢?其实原因就是obj=prototype
    {...}这段代码覆盖了原有对象obj的prototype属性

        首先我们来回顾一下一个对象实例是如何创建的:构造函数把它的prototype原型对象中的所有属性及方法拷贝一份给新的实例。
    在这里我的构造函数就是function Obj(){},而constructor也是创建实例的构造函数(即Obj)的引用。但是我们是通过this方式来
    调用的,那么我们应该调用的是由构造函数Obj的prototype所拷贝而来的所有的属性和方法,但是我们发现通过Obj.prototype{...},
    构造函数的prototype除了_init, method1, method2之外无任何其他方法(of course,constructor方法也没有,所以this.constructor失效了~~~)。改进的方法很简单,就是不要去覆盖prototype,而是要向prototype对象追加属性和方法。所以改进后的方法可能是这样的:
    function Obj() {
        this.prop1 = 'prop1'; 
    // instance property
        this.prop2 = 'prop2';
        
        this._init();
    }
    Obj.prototype._init = 
    function () {
        this.constructor.staticProp = 'Static Prop';
        this.constructor.staticMethod = 
    function () {
            
    // do some static behavior
        };
    };
    Obj.prototype.method1 = 
    function() {
            
    // do somthing
    };
    Obj.prototype.method2 = 
    function() {
            
    // do somthing
    };

    虽然我也不是很赞成去修改原始对象,但有时真的会起到事半功倍的效果。在这里我再向大家推荐一种方法,就是向Funtion对象的prototype属性中追加方法(这样以后所有的function函数对象就都具备了这个方法。其实用function定义的函数都是Function类的实例化),代码如下:
    Function.prototype.extend = function (oContext, bIsStatic) {
        var oThis = (typeof bIsStatic != 'undefined' && bIsStatic)? this: this.prototype;
        for ( var prop in oContext) {
            oThis[prop] = oContext[prop];
        }
    };
    function Obj() {
        this.prop1 = 'prop1'; // instance property
        this.prop2 = 'prop2';
    }
    // Append Static Methods or Properties
    Obj.extend({
        staticProp: 'staticProp',
        staticMethod: function () {
            // do some static behavior
        }
    }, true);
    // Append Instance Methods or Properties
    Obj.extend({
        method1: function() {
            // do somthing
        },
        method2: function() {
            // do somthing
        }
    });

    利用我刚才定义的extend方法,就可以轻松而又简洁地向Obj类中添加静态和实例属性或方法,而且已经解决上面所提到的所有问题。

  • 相关阅读:
    python-初始网络编程
    mysql 之优化
    python 操作Mysql
    白话SCRUM之一:SCRUM 的三个角色
    白话SCRUM 之三:sprint backlog
    Scrum 之 product Backlog
    9.为什么要进行系统拆分?如何进行系统拆分?拆分后不用 dubbo 可以吗?
    8.如何自己设计一个类似 Dubbo 的 RPC 框架?
    7.分布式服务接口请求的顺序性如何保证?
    6.分布式服务接口的幂等性如何设计(比如不能重复扣款)?
  • 原文地址:https://www.cnblogs.com/objectorl/p/1632726.html
Copyright © 2011-2022 走看看