mixin一般翻译为“混入”、“混合”, 早期一般解释为:把一个对象的方法和属性拷贝到另一个对象上; 也可以简单理解为能够被继承的类, 最终目的是实现代码的复用。
为了使你能够最快的清楚我在说什么,我们从一个需求说起:
一个项目中有多个弹层需求; 一些是公共方法,比如点击关闭按钮关闭弹层; 一些弹层是可以拖动的,且有蒙层; 一些弹层是可以缩放的; 其他都是业务方法,无可复用性。
你可以先在心里想下,如果是你,你会怎样完成这个需求?
我们为公共方法写个类:BaseModal 为可拖动的弹层写个类:DragModal 为可缩放的弹层写个类:ScaleModal 为自定义的业务需求写个类:CustomModal,画个脑图的话,会是下面图片中的样子:
// 公共方法 class BaseModal { close(){ console.log('close'); } } // 可以拖动的弹层,我们写一个单独的类 class DragModal extends BaseModal { hasLayer = true; drag() { console.log('drag'); } } // 可以缩放的弹层,我们写一个单独的类 class ScaleModal extends BaseModal { scale() { console.log('scale'); } } // 业务方法 class CustomModal extends DragModal { close(){ console.log('custom-close'); } do() { console.log('do'); } } let c = new CustomModal(); d.close(); // custom-close c.drag(); // drag c.do(); // do c.hasLayer; // true
// 可以拖动的弹层,我们写一个单独的类
class DragModal extends BaseModal {
hasLayer = true;
drag() {
console.log('drag');
}
}
// 可以缩放的弹层,我们写一个单独的类
class ScaleModal extends BaseModal {
scale() {
console.log('scale');
}
}
// 获取原型对象的所有属性和方法
function getPrototypes(ClassPrototype) {
return Object.getOwnPropertyNames(ClassPrototype).slice(1);
}
function mix(...mixins){
return function(target){
if (!mixins || !Array.isArray(mixins)) return target;
let cp = target.prototype;
for (let C of mixins) {
let mp = C.prototype;
for (let m of getPrototypes(mp)) {
cp[m] = mp[m];
}
}
}
}
@mix(DragModal, ScaleModal)
class CustomModal extends DragModal {
scale(){
console.log('custom-scale');
}
do() {
console.log('do');
}
}
let c = new CustomModal();
c.close(); // 报错,因为dobase没在A或B的prototype上,而是在A.prototype.__proto__上
c.drag(); // drag
c.scale(); // scale 并非是我们想要的custom-scale
console.log(c.hasLayer); // undefined
以上mix方式实现了多继承,但存在以下问题
class BaseModal {
close() {
console.log('close');
}
}
let DragModalMixin = (extendsClass) => class extends extendsClass {
hasLayer = true;
drag() {
console.log('drag');
}
};
class CustomModal extends DragModalMixin(BaseModal) {
drag() {
console.log('custom-drag');
}
do() {
console.log('do');
}
}
let c = new CustomModal();
c.close(); // close
c.drag(); // custom-drag
console.log(c.hasLayer); // true
如何让CustomModal再继承ScaleModal呢? 其实很简单,在上面基础上,我们再写一个ScaleModalMixinMixin类就可以了
class BaseModal {
close() {
console.log('close');
}
}
let DragModalMixin = (extendsClass) => class extends extendsClass {
hasLayer = true;
drag() {
console.log('drag');
}
};
let ScaleModalMixin = (extendsClass) => class extends extendsClass {
scale() {
console.log('scale');
}
};
class CustomModal extends ScaleModalMixin(DragModalMixin(BaseModal)) {
drag() {
console.log('custom-drag');
}
do() {
console.log('do');
}
}
let c = new CustomModal();
c.close(); // close
c.drag(); // custom-drag
c.scale(); // scale
console.log(c.hasLayer); // true
这种方式不会修改父类的原型对象,但是如果存在跟父类同名的方法,只会执行父类的,而不回执行被继承的类的方法,那么如何使相同方法分别执行呢?
class BaseModal {
close() {
console.log('close');
}
}
let DragModalMixin = (extendsClass) => class extends extendsClass {
hasLayer = true;
drag() {
console.log('drag');
}
};
let ScaleModalMixin = (extendsClass) => class extends extendsClass {
scale() {
console.log('scale');
}
close() {
console.log('scale-close');
if (super.close) super.close();
}
};
class CustomModal extends ScaleModalMixin(DragModalMixin(BaseModal)) {
close() {
console.log('custom-close');
if (super.close) super.close();
}
do() {
console.log('do');
}
}
let c = new CustomModal();
c.close(); // custom-close -> scale-close -> close
Mixin是一种思想,用来实现代码高度可复用性,又可以用来解决多继承的问题,是一种非常灵活的设计模式,如果你多多琢磨,相信你也会发现一些其他的妙用的,看好你哟!
原文来源:https://github.com/ronffy/mixin-class
JS语言传统创建对象的方法一般是通过构造函数,来定义生成的,下面是一个使用function生成的例子。ES5是先新建子类的实例对象this,再将父类的属性添加到子类上,由于父类的内部属性无法获取,导致无法继承原生的构造函数
ES6 提供了更接近传统语言的写法,引入了 class(类)这个概念,作为对象的模板。通过class关键字,可以定义类
JS基于原型的类,一直被转行前端的码僚们大呼惊奇,但接近传统模式使用class关键字定义的出现,ES6的class只是个语法糖,其定义生成的对象依然构造函数。不过为了与构造函数模式区分开,我们称其为类模式。
class 是 ES6 的新特性,可以用来定义一个类,实际上,class 只是一种语法糖,它是构造函数的另一种写法。用法和使用构造函数一样,通过 new 来生成对象实例
ES6中的 class定义一个类, 其内部包含 constructor构造函数, 除了在构造函数显示的定义一些属性, 其余的默认都添加到这个类的原型对象上。以上代码 classProxy(prosen2) 返回的是包含一层拦截器的实例对象, 当读取 sayName这个函数的是和会出发 get拦截等操作。
使用jQuery可以给元素很方便的添加class和删除class等操作,现在原生的JavaScript也可以实现这个方法了。使用classList可以方便的添加class、删除class、查询class等。elementClasses 是一个 DOMTokenList 表示 element 的类属性 。
proposal-class-fields与proposal-private-methods定义了 Class 的私有属性以及私有方法,这 2 个提案已经处于 Stage 3,这就意味着它们已经基本确定下来了,等待被加入到新的 ECMAScript 版本中。
ES6中新增了class这个语法糖。此class并非java中的class,ES6中的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。其中有static关键字。
vue 指令以 v- 前缀标示,数据绑定的指令 v-bind:属性名, 简写为 :属性名, 简单的数据绑定例子如下;vue 的分隔符默认是 {{ }}, 在分隔符里面的字符串会被认为是数据变量,可以通过 方式设置class
class (类)作为对象的模板被引入,可以通过 class 关键字定义类。类简要说明,类的本质是function,是基本原型继承的语法糖。所以,JS中继承的模型是不会被改变的。
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!