body click js 委托_JavaScript基础-行为委托

a99d5e03860c3ef3cba86c1f18fa785b.png

JavaScript基础-行为委托

JavaScript中的原型链的机制就是对象之间的关联关系,然后就存在了行为委托的说法
委托行为就意味着某些对象在找不到属性或者方法的情况下,会把这个请求委托给另外一个对象

1. 类与对象

纯JavaScript风格实现类风格的代码,将使用jQuery来操作dom和css

// 父类
// 定义内部属性
function Widget(width, height){
    this.width = width || 50;
  this.height = height || 50;
  this.$elem = null;
}
// 渲染的方法
Widget.prototype.render = function($where) {
    if(this.$elem){
    // 样式
    this.$elem.css({
        width: `${this.width}px`,
      height: `${this.height}px`
      // 放到哪个位置上
    }).appendTo($where)
  }
}
// 子类
function Button(width,height,label) {
    // 调用“super”构造函数
  // 丑陋的显式伪多态 
  Widget.call(this, width, height);
  this.label = label || "Default";
  this.$elem = $("<button>").text(this.label);
}
// 让Button“继承”Widget
Button.prototype = Object.create(Widget.prototype);
// 重写render(...)
Button.prototype.render = function($where){
    // “super”调用
  // 丑陋的显式伪多态 ,从子类方法中引用父类的基础方法,呸!!丑陋
  Widget.prototype.call(this, $where);
  this.$elem.click(this.onclick.bind(this)); // 绑定
}
Button.prototype.onclick = function(evt){
    console.log(`Button ${this.label} clicked!`)
}
$(document).ready(function(){
    var $body = $(document.body);
  var btn1 = new Button(125, 30, "Hello");
  var btn2 = new Button(150, 40, "world");
  btn1.render($body);
  btn2.render($body);
})


ES6的class语法糖

class Widget{
    constructor(width, height){
    this.width = width || 50;
    this.height = height || 50;
    this.$elem = null;
  }
  render($where){
    if(this.$elem){
    // 样式
    this.$elem.css({
        width: `${this.width}px`,
      height: `${this.height}px`
      // 放到哪个位置上
    }).appendTo($where)
    }
  }
}

class Button extends Widget {
    constructor(width,height,label){
    super(width,height);
    this.label = label || "Default";
    this.$elem = $("<button>").text(this.label);
  }
  render($where){
    super.render($where);
    this.$elem.click(this.onclick.bind(this)); // 绑定
  }
  onclick(evt){
        console.log(`Button ${this.label} clicked!`)
    }
}
$(document).ready(function(){
    var $body = $(document.body);
  var btn1 = new Button(125, 30, "Hello");
  var btn2 = new Button(150, 40, "world");
  btn1.render($body);
  btn2.render($body);
})

委托设计模式的

var Widget = {
    init:function(width,height){
    this.width = width || 50;
    this.height = height || 50;
    this.$elem = null;
  },
  insert:function($where){
    if(this.$elem){
      // 样式
      this.$elem.css({
        width: `${this.width}px`,
        height: `${this.height}px`
        // 放到哪个位置上
      }).appendTo($where)
    }
  }
}
var Button = Object.create(Widget);
Button.setup = function(width, height) {
    // 委托调用
  this.init(width, height);
    this.label = label || "Default";
  this.$elem = $("<button>").text(this.label);
}
Button.build = function($where){
    // 委托调用
  this.insert($where);
    this.$elem.click(this.onclick.bind(this));
}
Button.click = function(evt){
    console.log(`Button ${this.label} clicked!`)
} 
$(document).ready(function(){
    var $body = $(document.body);
  var btn1 = Object.create(Button);
  btn1.setup(125,30,"hello");
  var btn2 = Object.create(Button);
  btn2.setup(130,40,"world");

  btn1.build($body);
  btn2.build($body);
})

在委托设计模式中,这种对象关联风格代码相比传统原型风格代码有优势的地方,使用类构造函数的话,你需要在同一步骤中实现构造和初始化,然而许多情况把这两步分开像对象关联代码一样更灵活

2. 更好的语法

使用class语法糖,还有简洁方式声明

class Foo(){
 getUser() {/*...*/}
}

简洁语法实际上会变成一个匿名函数表达式并赋值给getUser,(function(...){})
一般匿名函数没有name标识符,这会导致:

  1. 调用栈更难追踪;
  2. 自我引用(递归,事件的绑定解除等等)更难;
  3. 代码(稍微)更难理解;


简洁语法方式无法避免的是第2点 ,其他的话,因为是特殊性,也会有给函数对象设置一个内部的name属性
如果需要自我引用的话,就要使用具名函数表达式了

var Foo = {
    bar: function(x){
    if(x<10){
        return Foo.bar(x*2);
      }
    return x;
  },
  // 当多个对象通过代理共享函数,使用this绑定的话,就要使用下面 的name标识符来真正引用
  baz: function baz() {
    if(x) {
        return baz(x*2)
       }
    return x;
  }
}

3. 内省

内省就是检查实例的类型,主要目的是通过创建方式来判断对象的结构和功能

function Foo(){/*...*/}
Foo.prototype...

function Bar(){/*...*/}
Bar.prototype = Object.create(Foo.prototype);
var b1 = new Bar("b1");

// 让Foo和Bar互相关联 
Bar.prototype instanceof Foo;// true
Object.getPrototypeOf(Bar.prototype) === Foo.prototype; //true
Foo.prototype.isPrototypeOf(Bar.prototype);// true

// 让b1关联到Foo和Bar
b1 instanceof Foo;// true
b1 instanceof Bar;// true
Object.getPrototypeOf(b1) === Bar.prototype; //true
Foo.isPrototypeOf(b1);// true
Bar.isPrototypeOf(b1);// true

上面 这种做法,很容易人理解成是继承关系,它们只不过是关联关系而已,但是也只能这样子
还有一种更加脆弱的内省模式,但是在开发者上面用的很多

if(a1.something){   
    a1.somethinf();   
}

这种方法就是,例如需要判断一个对象引用是否是Promise,但是判断的方法是检查对象是否有then()的方法,就可以判断它具有Promise的所有标准行为,但是也有一定的危险性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值