美文网首页
3-安全/扩展内置对象 原型链(属性搜索原则) 继承实现的6种方

3-安全/扩展内置对象 原型链(属性搜索原则) 继承实现的6种方

作者: 前端雨 | 来源:发表于2017-11-27 21:14 被阅读0次

    扩展内置对象

    • 内置对象: Object | Array | Date | Function | String ...
    • 扩展: 给内置的对象添加属性和方法
    • 注意: 此方法可以达到扩展内置对象的效果.
      • 不建议使用: 在实际开发中, 可能多人合作开发. 若多人以此方法扩展对象, 代码难以维护, 可能代码被覆盖导致安全性差

    安全的扩展内置对象

    • 核心操作
      • 自定义一个构造函数
      • 设置这个构造函数的原型对象是内置构造函数的一个实例


        内置扩展对象
        代码实现结构图

    原型链

    • 原型链的顶端: Object.prototype
      • 原型链最顶端的原型: Object.prototype.__proto__ = null;
    • 原型链结构
      1. 每个对象都是由构造函数创建出来的
      2. 每一个构造函数都有对应的原型对象
      3. 构造函数的原型对象也是一个对象
      4. 因此, 构造函数的原型对象也有构造函数
      5. 构造函数的原型对象的构造函数也有原型对象, 这个原型对象也是一个对象
        原型链定义

    原型链中属性的搜索原则

    • 就近原则
      • 访问对象属性时, 先查找自身是否有该属性, 有直接使用
      • 若没有, 就访问这个对象的原型对象是否有, 有就直接使用
      • 若没有, 会访问这个对象原型对象的原型对象上是否有, 如果有就直接使用
      • 直到Object的原型对象, 若没有, 则返回undefined(属性)或报错(方法)


        原型链属性的访问原则

    继承的实现

    1. 属性拷贝(混入式继承)
      • 方法: 如果属性的值是引用类型的数据, 子对象和父对象共享同一份数据, 修改其中一个会影响另一个

          var obj = {name : 'zs',age : 20,friends:['小明','小红']};
          var  obj1 = {};
          // 需求:obj1获取obj的属性
        
          for(var key in obj){
              obj1[key] = obj[key];
          }
          // 修改了obj1的friends对obj的friends会有影响,因为他们存储的是同一个数组的地址
          obj1.friends.push('老王');
          console.log(obj1);
          console.log(obj);
        
      • 函数: Object.assign(子对象, 父对象1, 父对象2,...);

    2. 原型式继承
      • 方法: 父构造函数的原型对象赋值给子构造函数的原型对象(替换原型Son.prototype = Father.prototype)
      • 问题
        • 创建出来的对象, 构造器属性, 默认指向父构造函数
          • 无法通过构造器属性进行修改
        • 不能获取实例属性/方法, 只能获取父构造函数原型对象的属性和方法
    3. 原型链继承
      • 方法

        • 提供一个父构造函数
        • 提供一个子构造函数
        • 设置子构造函数的原型对象是父构造函数的实例
      • 注意点

        • 修正构造器属性: 要在设置原型链继承之后
        • 设置原型对象的属性: 要在设置原型链继承之後
        • 设置了原型链继承之後, 只能利用对象的动态特性设置原型对象, 不能使用字面量的方式


          原型链的注意点
      • 问题

        • 无法传递参数给父构造函数-13
        • 继承过来的实例属性会成为原型属性, 对创建出来的对象存在数据共享的问题
    4. 复杂的原型链实例
      • 注意点: 同原型链继承一样
    5. 借用构造函数继承
      • 方法: 只能获取实例属性和方法, 不能获取原型属性和方法
    6. 组合继承
      • 方法
        • 借用构造函数继承获取实例属性和方法
        • 使用原型链继承获取原型属性和方法


          组合继承的基本写法

    Object.create()

    • 定义: 创建一个新的对象, 并且设置这个对象的原型对象是传入的参数
    • 兼容: ES5支持

    call() | apply()

    • 在ES3, 给Function的原型对象添加2个方法
      • Function.prototype.call | Function.prototype.apply
    • 作用: 借用其他对象的方法
    • 参数
      • 第一个参数: 调用方法的对象(函数内部this的绑定对象)
      • 后面的参数:
        • call 参数列表 参数1, 参数2...

        • apply 参数列表[参数1, 参数2]

          //打印1: 期望传递一个参数(参数列表可不传)
          console.log(Function.prototype.call.length);  
          //打印2: 期望传递两个参数(调用对象的数组, [])
          console.log(Function.prototype.apply.length);  
          

    深拷贝/浅拷贝

    • 浅拷贝: 引用类型数据只拷贝到地址
    • 深拷贝: 内容拷贝
      • 实现
        1. 提供一个函数, 函数有2个参数, 一个目标对象, 一个要拷贝属性的对象
        2. 判断: 第一个参数是否有值
        3. 遍历第二个参数, 判断属性值的类型
          • 如果是值类型的数据就直接赋值
          • 如果是引用类型的数据, 就再一次调用这个方法拷贝内部存储的数据

    Array.isArray()

    • 定义: 判断一个对象是否是数组

    • ES5的方法, ES5之前不支持,故存在兼容性问题

        // 兼容写法
        if (!Array.isArray) {
          Array.isArray = function(arg) {
          return Object.prototype.toString.call(arg) === '[object Array]';
          };
        }
      
    • 其他方法:
      Object.prototype.toString.call()

        let a = [1,2,3]
        Object.prototype.toString.call(a) === '[object Array]';//true
        //检验是否是函数
        let a = function () {};
        Object.prototype.toString.call(a) === '[object Function]';//true
        //检验是否是数字
        let b = 1;
        Object.prototype.toString.call(a) === '[object Number]';//true
      
        //PS: 甚至对于多全局环境时, Object.prototype.toString().call()也能符合预期处理判断。
        //为body创建并添加一个iframe标签
        var iframe = document.createElement('iframe');
        document.body.appendChild(iframe);
        //取得iframe对象的构造数组方法
        xArray = window.frames[window.frames.length-1].Array;
        //通过构造函数获取一个实例
        var arr = new xArray(1,2,3); 
        console.log(Object.prototype.toString.call(arr) === '[object Array]');//true
        
        // 另外两种方法:存在多个全局环境的问题
        arr instanceof Array;//false  
        arr.constructor === Array;//false
      
      
      

    相关文章

      网友评论

          本文标题:3-安全/扩展内置对象 原型链(属性搜索原则) 继承实现的6种方

          本文链接:https://www.haomeiwen.com/subject/gzcjbxtx.html