-
-
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; | |
}; */ | |
iwill
commented
Mar 11, 2016
•
不能说一毛一样,但实在是 太像了 😎😎
// class
const Person = class {
constructor(name) {
this.name = name;
this.friends = [];
}
makeFriend(person) {
this.friends.push(person.name);
}
};
// subclass
const Student = class extends Person {
constructor(name, grade) {
// super constructor
super(...arguments);
this.grade = grade;
}
makeFriend(person) {
// super method
super.makeFriend(...arguments);
}
}
如果您想改进这个代码,以下是一些建议:
可以使用 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;
}
参考: