-
-
Save iwill/2303057 to your computer and use it in GitHub Desktop.
| /*! | |
| * Javascript library - $class 2.0.0 | |
| * https://gist.github.com/iwill/2303057 | |
| */ | |
| export default function $class(source, SuperClass) { | |
| // default values | |
| SuperClass = SuperClass || Object; | |
| source = source || {}; | |
| // constructor & super constructor | |
| source.constructor = source.hasOwnProperty("constructor") ? source.constructor : function() { | |
| SuperClass.apply(this, arguments); | |
| }; | |
| // class & prototype | |
| const Class = source.constructor; | |
| Class.isPlainObject = true; | |
| Class.prototype = new SuperClass(); | |
| // override Class.prototype[each] by source[each] | |
| for (let each in source) { | |
| Class.prototype[each] = source[each]; // include `constructor` | |
| } | |
| return Class; | |
| } | |
| /** | |
| * $class 1.0.0 | |
| this.$class = function(src) { | |
| src.constructor.prototype = src; | |
| return src.constructor; | |
| }; */ | |
如果您想改进这个代码,以下是一些建议:
可以使用 ECMAScript 6 中的 class 语法来定义类,因为它是更直观和更简洁的。
默认的构造函数应该在调用 SuperClass 构造函数之前检查它是否存在,以避免 TypeError。
源对象可能包含额外的属性,这些属性不应该在类原型中复制。因此,可以使用 hasOwnProperty 方法来检查该属性是否是 source 对象的自身属性,仅复制自身属性。
该函数可能会影响到原型链,因此请小心使用它。考虑使用 Object.create 方法来设置类原型,以避免影响到原型链。
—— ChatGPT
刚刚给 Class 增加了一个属性:Class.isPlainObject = true;,用来说明它的实例是 plain object —— 所有的属性都可遍历、可修改。
原本考虑用 Object.defineProperty(Class, "isPlainObject", { value: true }); 避免 isPlainObject 属性被修改,但是这好像偏离了本意,是的 isPlainObject 本身也应该可遍历、可修改。
做这个改动,主要源于最近用到的对 Object 的判断,判断的方法千奇百怪,逻辑其实有两种:
- A: 严格的
Object的直接实例,即所谓的 plain object - B:
Object子类的实例
本来 Object 子类的实例也不该被区别对待的,可是有两种特殊情况:区分数组和对象,以及用遍历所有属性。前者还好,有 Array.isArray() 可用,可是 ...
期盼已久的 ES6 的 class 并不如想象中那样完美,虽然有了 class、extends、constructor、get、set、static,也支持了私有属性,但是 get 定义的属性不能遍历、不能序列化成 JSON,
要用 Object.defineProperty(this, k, { value: v, enumerable: true })
或者 Object.defineProperties(this, { k: { value: v, enumerable: true } })
定义才行,不愧是 JavaScript 啊,一如既往的蛋疼。
所以,对 Object 的判断我偏向于 plain object 了。为了避免传统的 function + prototype 方式创建的 plain object 被误伤,我在 $class 创建的 Class 中添加了 isPlainObject 属性,注意是 Class 的属性,通过示例要这样访问 object.constructor.isPlainObject 访问。
function isObject(o) {
return o?.constructor == Object || o?.constructor?.isPlainObject;
}参考:
不能说一毛一样,但实在是 太像了 😎😎