Git Product home page Git Product logo

oo's People

Contributors

bobshen avatar exodia avatar otakustay avatar yanghuabei avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oo's Issues

增加一个可用于class上的defineAccessor

如果我们写ES6:

import oo from 'eoo';

/**
 * 用户信息面板类
 *
 * @class common.Account
 */
class Account {
    /**
     * 初始化
     *
     * @method common.Account#init
     */
    init() {
        // ...
    }
}

oo.defineAccessor(Account.prototype, 'globalData');
oo.defineAccessor(Account.prototype, 'widgetContainer');
oo.defineAccessor(Account.prototype, 'templateEngine');

这个defineAccessor就比较奇怪,是不是能有个defineAccessorFor方法,直接给class?

增加 defineMembers 方法

之前只能在创建类的时候传入原型链对象,无法尽早看到继承关系,增加后的代码可以下面这样:

var A =  Class();
var exports = { //xx };
Class.defineMembers(A, exports);

提供直接继承静态对象的功能

相当于Object.create,以下是摘自MDN的代码:

if (typeof Object.create != 'function') {
    (function () {
        var F = function () {};
        Object.create = function (o) {
            if (arguments.length > 1) { throw Error('Second argument not supported');}
            if (o === null) { throw Error('Cannot set a null [[Prototype]]');}
            if (typeof o != 'object') { throw TypeError('Argument must be an object');}
            F.prototype = o;
            return new F();
        };
    })();
}

Object.setPrototypeOf与oo生成的class冲突

示例代码:

let Super = oo.create({});
let Sub = function () {};
Object.setPrototypeOf(Sub, Super);
Sub.toString(); // StackOverflow

原因分析:

  1. oo创建class时会赋值kclass.toString
  2. toString的实现实际上是this.prototype.constructor.toString()
  3. Object.setPrototypeOf会让Sub.toStringSuper.toString相同
  4. Sub.prototype.constructor其实就是Sub自身
  5. 因此toString()会导致死循环

更进一步:

这个问题不仅仅存在于setPrototypeOf上,当一个“继承”函数同时满足以下条件:

  1. 会修正prototype.constructor为自身
  2. 会把静态方法都继承过来

的情况下,这个toString()就会导致死循环

是否增加 Class.prototype.extend方法

即给类对象增加快捷继承出一个新类的方法:

var Super = Class(superExports);
var Sub = Super.extend(SubExports);

等价:

var Super = Class(superExports);

var Sub = Class(Super, SubExports);

增加元数据?

有群众普遍反映,在console中看通过eoo.create创建出来的类,是一堆klass,完全看不出具体是哪个类

我是这么想的,像在java之类的语言中,有一个重要的特性叫反射,即可以将类、方法、参数的元信息提取出来,用于动态地操作这个类,而eoo可以借鉴一下这一点

我设想的思路是,变成eoo.create({Function} parent, {Object} exports, {Object} meta),其中meta我们暂定包含一个name属性,后续可以扩充

当有meta参数时,取里面的name属性来动态生成类名(用new Function生成就行),在之后也能再加accessibility: 'public | internal | private'之类的其它数据

然后eoo提供一个getMetaOf(someClass)的方法来获取这些元信息,方法名是参考Object.getPrototypeOfObject.getOwnPropertyDescriptor来的

以前觉得为了调试来加一个参数是不好的,现在想想从元数据的角度来看,似乎能合理解释

带逻辑的setter和getter

有时候settergetter是有逻辑的,但是又希望可以利用oo隐藏掉具体的属性强制只能使用getter访问,是否有可能实现类似的功能。

有2个想法,第一种是静态方法:

exports.setFoo = function (value) {
    value.bar = true;
    oo.set(this, 'foo', value);
};

exports.getFoo = function () {
    var value = oo.get(this, 'foo');
    value.bar = false;
    return value;
};

第二种是hook模式:

oo.defineAccessor(
    exports,
    'foo',
    {
        getHook: function (value) {
            // value是oo拿到的
            value.bar = false;
            return value; // 返回给外面
        },
        setHook: function (value) {
            // value是传进来的
            value.bar = true;
            return value; // 随后会被真正set
        }
    }
);

定义私有成员

var exports = {};
exports.$privae = {};
exports.$private.privateMethod = function () {};
exports.$private.privateMember = 'private';
exports.publicMethod = function () {
    this.privateMethod();
};

var MyClass = oo.Class(exports);

var instance = new MyClass();
instance.publishMethod();

instance.privateMethod() // throw error;
instance.privateMember() // throw error

实现上:

会借助Object.defineProperty的 getter/setter 和 caller__owner__ 来做限制,ie8下不做支持,毕竟我们的开发调试流程是在支持es5的环境下下进行的,仅仅是定义了开发模型,不会对 ie8造成功能影响。

License

我们的开源项目应该都是基于 BSD 的,现在 oopackage.json 里用了 GPL,改掉吧不然不好搞了……

增加Class.defineStatics方法

用于给类定义静态成员:

var A = Class();
var statics = { staticA: 1 };
Class.defineStatics(A, statics);
A.staticA; // 1

基于类 weakmap 的私有成员实现

实现见: https://github.com/ecomfe/oo/tree/feature/private-weakmap-like

使用方式如下:

// User.js
var $private = oo.createPrivate({
      privateMethod: function () {
            // 获取私有属性
             return $private(this).privateProp;
      },
      privateProp: 'private'
}); 

var exports = {
      constructor: function () {
             this.$super(arguments);
            // 设置实例上的私有属性
           $private(this).instancePrivateProp = 'instance';
      },
      publicMethod: function () {
           // 调用私有方法
            var result = $private(this).privateMethod.call(this);
           return result + $private(this).instancePrivateProp;  
      }
};

var User = oo.create(exports);

优点在于:

  • 兼容性好,ie系,严格模式都可以正常运行。
  • 性能应该也不错,内部不是用 weakmap,而是在实例上挂个uid,通过 uid 去找对应的私有成员,应该会比 symbol 更快。
  • 基于此实现 protect 特性很容易。

不足在于:

  • 写法可能有点不舒服,调用私有方法必须用 call 去改变作用域到实例上
  • 不如 property 和 symbol 的方式来得直观
  • 私有方法可能用闭包会比这种方式来得省事,但该方案更适合于需要在实例上挂私有属性的场景。

@otakustay @Justineo 我个人倾向于用类 weakmap 的实现方案

支持通过defineProperty的getter/setter定义

在我们放弃IE8后,我的视野好像确实大了些- -

希望提供一个definePropertyAccessor的功能,使用defineProeprty来定义一个getter/setter的属性,功能和现在的defineAccessor是一样的就行

这里不使用普通的属性,而是要一个没有逻辑的getter/setter,目的是让uioc能更好地发现需要注入的属性而实现自动注入功能

Object.create第一个参数传入非object/function类型参数

当传入非object/function类型参数时,Object.create返回的类的实例调用this.$super报错。因此,对非object/function型参数需要进行处理。
如:

var A = Class.create(1, {
    constructor: function () {
        this.$super(arguments);
    }
});
new A(); // TypeError: Cannot read property 'constructor' of undefined

增加快捷定义 accessor 方法

类似require('eoo').defineSimpleGetterAndSetter(exports, 'globalData')

使用者无法直接通过 this.globalData访问到属性,需要通过 set/getGlobalData方式获取

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.