最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • JavaScript 语言精粹四(继承)

    正文概述 掘金(poo)   2021-01-01   355
    ...往往会把一件完整的东西化成无数的形象,如凹凸镜一般,正面望去,一片模糊 - 威廉·莎士比亚《理查二世》

    起步:

    • 多数编程语言中,继承都是一个重要的主题
    • 基于类的语言中(如JAVA),继承提供两个重要的服务
      • 代码复用,显著减少软件开发成本
      • 类继承可以引入一套类型系统规范,减轻工作量
    • JavaScript 是一门弱类型语言,不需类型转换,无需关注对象继承关系
    • JavaScript 提供一套更丰富的代码复用模式,可模拟基于类的模式
    • JavaScript 是一门基于原型的语言,意味着对象直接从其他对象继承

    伪类

    • javascript 中某些复杂语法看起来像那些基于类的语言,它不直接让对象从其它对象继承,反而是使用构造器函数产生对象

      • 当函数对象被创建时,Function 构造器产生的函数对象会运行:
      this.prototype = { constructor: this };
      
      • 新对象被赋予 prototype 属性,(值是包含constructor属性,且属性值为该新函数的对象)
      • prototype 用以存放继承特征javascript 中每个函数都包含 prototype 属性
      • 当采用构造器调用模式时,(使用 new调用),函数的执行方式会改变
    • 定义一个构造器,并扩充它的原型

      var Man = function (name) {
        this.name = name;
      };
      Man.prototype.getName = function () {
        return this.name;
      };
      Man.prototype.says = function () {
        return this.saying || "";
      };
      
    • 构造实例

      var myName=new Man('poo');
      var name=myName.getName();
      console.log(name);// poo
      
    • 还可以构造另一个伪类继承 Man,

      var Dog=function(name){
        this.name=name;
        this.saying='aHa';
      }
      Dog.prototype=new Man();//替换它的prototype
      Dog.prototype.wangwang=function(n){
        var i,txt='';
        for(i=0;i<n;i++){
          s=s?s+='~':'汪'
        }
        return txt;
      }
      var yourDog=new Dog('花花')
      var says=yourDog.says();// aHa
      var wangwang=yourDog.wangwang(3);//汪~~
      
    • 使用构造器有一个严重的危害,调用构造器函数时,若没在前面加上 new,则this 不会绑定到新对象上,反而绑定到了全局,破坏了全局变量环境

    • 为了降低这个风险,构造器函数约定俗成首字母大写。

    对象说明符

    • 通常构造器要接受一些参数,为避免记错顺序引起的问题
    • 一般都会使用一个简单的对象说明符来描述
    • 这样就不必在意它的顺序了,而且也更易于阅读使用。例如:
    var myObj=maker(a,b,c,d);
    //---以上可写为
    var myObj=maker({
      isa:a,
      isb:b,
      isc:c,
      isd:d
    })
    

    原型

    • 基于原型的继承相比基于类的继承概念上更简单——即:新对象可以继承旧对象的属性
    • 例如,使用对象字面量构造一个对象
    var man = {
      name: "poo",
      getName: function () {
        return this.name;
      },
      says: function () {
        return this.saying || "";
      },
    };
    
    • 再利用Object.create方法构造出其他实例
    var myFriends = Object.create(man);
    myFriends.name = "tomato";
    myFriends.says = "Hi~  potato";
    myFriends.getName = function () {
      return this.name + " " + this.says;
    };
    
    • 通过定制新对象,来指定与基于的基本对象区别的方式,叫做差异化继承。

    函数化

    • 继承模式缺点在于数据私密性不强,因为对象中的属性都是可见的
    • 若想构造私有属性,那么可以使用 应用模块模式
    • 从构造一个可以生成对象的函数(它并不需要使用 new 操作符,因此命名不需大写)
      1. 创建新对象。使用Object.create方法
      2. 定义私有实例变量和方法,是函数中通过var语句定义的普通变量
      3. 给当前新对象扩充方法,使这个方法拥有访问参数及(2)中var声明的普通变量的特权
      4. 返回当前新对象。

    例如:

    var constructor=function(spec,my){
      var that,//-其他的私有实例变量
      my=my||{};
      //共享变量和函数添加到my中
      that=//一个新对象
      //添加给that的特权方法
      return that;
    }
    
    • my对象是一个为继承链中的构造器所提供私密共享的容器,my 对象可以选择性使用,若 my 为空,则创建一个 my 对象( my=my||{ }
    • 然后声明该对象私有的实例变量和方法,构造器的变量和内部函数都变成该实例的私有成员,内部函数可访问spec my that及其他变量。
    • 然后通过赋值语句,给my添加共享私有成员
     my.member=value
    
    • 然后构造新对象,将其赋值给that,再进行扩充,后边我就迷糊了,还没看懂。

    部件

    • 可以利用一套部件把对象组装出来,比如构造一个给对象添加时间处理的函数
    • 给对象添加on 方法,fire方法和私有事件注册表对象
    var eventuality = function (that) {
      var registry = {};
      /**
       * 在一个对象上触发一个事件
       * 可以是一个含事件名称的字符串
       * 或是一个 包含事件名的type属性的 对象
       * 通过 on 方法注册的事件处理程序中匹配事件名称的函数会被调用
       */
      that.fire = function (event) {
        var array,
          func,
          handler,
          type = typeof event === "string" ? event : event.type;
        //若该事件存在一组事件,则遍历且顺序执行
        if (registry.hasOwnProperty(type)) {
          array = registry[type];
          for (let i = 0; i < array.length; i++) {
            handler = array[i];
            //每个处理程序中包括一个方法和一组可选参数
            //若该方法是字符串形式的,则找到该函数
            func = handler.method;
            if (typeof func === "string") {
              func = this[func];
            }
            //调用此处理程序,若该条包括参数,则传递,否则传递该对象
            func.apply(this, handler.parameters || [event]);
          }
        }
        return this;
      };
      //注册一个事件,构造一条处理程序条目,将其插入处理程序数组
      //若此类型事件不存在则构造
      that.on = function (type, method, parameters) {
        var handler = {
          method: method,
          parameters: parameters,
        };
        if (registry.hasOwnProperty(type)) {
          registry[type].push(handler);
        } else {
          registry[type] = [handler];
        }
        return this;
      };
      return that;
    };
    
    • 可在任何单独对象上调用eventuality,授予其事件处理方法,也可在that返回前在构造器函数中调用它。
    eventuality(that);
    
    • 当前这种方式中:

      • 一个构造器函数可从一套部件中组装出对象
      • 因为JavaScript弱类型语言的原因,所以无需去了解对象在类型系统中的继承关系
      • 若想eventuality访问该对象私有状态,则可把私有成员集合my传递进去

    总结:


    起源地下载网 » JavaScript 语言精粹四(继承)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元