对象的访问机制及其他

105 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情

对象访问机制

        当访问一个对象的成员时

        如果对象自己本身有, 直接返回结果给你, 停止查询

        如果对象自己本身没有, 会自动去 proto 上访问

        有就返回结果, 停止查询。

利用 prototype 和 proto 和 对象访问机制

        解决了构造函数的不合理

        属性直接写在 构造函数体内

        方法书写在 构造函数的 prototype 上

        使用构造函数创建一个 有属性 有方法 合理的 对象

        prototype 作用: 就是为了书写一些方法给该构造函数的实例对象使用

function Person(name, age) {     
this.name = name;    
this.age = age;  
}
 Person.prototype.sayHi = function () { 
 console.log('hello world') }
    // 使用 Person 创建一个对象   
    let p1 = new Person('Jack', 18);   
    console.log(p1);
    // 当我访问 p1.name 的时候, 自己就有  
    console.log(p1.name);   
    p1.sayHi();

    // 再次创建一个实例化对象   
    let p2 = new Person('Rose', 20);   
    p2.sayHi();

       

构造函数相关的 this 指向

        1. 构造函数体内的 this 指向

    和 new 关键字连用, this 指向当前实例

        2. 构造函数原型上的方法里面的 this 指向

    方法是依靠实例对象在调用

面向对象选项卡

  1. 抽象内容

        属性 btns、 tabs

      实现点击事件切换的方法

  1. 在方法里面实现选项卡

        循环绑定事件以后, 发现 this 指向不再是 实例了

        拿不到 btns 和 tabs

        解决方案 1:

          提前保存 this 为一个变量

        解决方案 2:

          使用箭头函数

          因为箭头函数没有 this, 外部作用域的 this

     

  function Tabs(ele, options = {})
  {      
  // 拿到出现选项卡的范围      
  this.ele = document.querySelector(ele)    
  // 找到 btns      
  this.btns = this.ele.querySelectorAll('ul > li')  
  // 找到 tabs     
  this.tabs = this.ele.querySelectorAll('ol > li')    
  // 初始化一下 options     
  this.options = options      
  this.change()    
  }
    Tabs.prototype.change = function () { 
    // 操作的是当前实例的 btns 和 tabs     
    // this 就是当前实例, 我们就要给 this.btns 的每一个添加点击事件      
    this.btns.forEach((item, index) => {        
    item.addEventListener(this.options.type || 'click', () => {          this.btns.forEach((t, i) =>
    {    
    t.className = ''      
    this.tabs[i].className = ''          })          
    // 给对应的添加类名        
    item.className = 'active'        
    this.tabs[index].className = 'active'       
    })      })    }   
    new Tabs('.box2', { type: 'mouseover' })  
    new Tabs('.box3');
    let t1 = new Tabs('.box', { type: 'click' }) 
    console.log(t1);

定义:

        1. 每一个函数天生自带一个属性叫做 prototype, 是一个对象

        2. 每一个对象天生自带一个属性叫做 proto 指向所属构造函数的 prototype

        3. 当一个对象, 没有准确的构造函数来实例化的时候, 我们都看作是内置构造函数 Object 的实例。

1. var arr = [] , Array 的实例
2. var obj = {} , Object 的实例
3. var p1 = new Person() , Person 的实例
4. var time = new Date() , Date 的实例
5. var fn = function () {} , Function 的实例
6. Person.prototype , Object 的实例
7. Array.prototype , Objec 的实例

结论:

        任何一个对象开始出发

        按照 proto 开始向上查找

        最终都能找到 Object.prototype

        我们管这个使用 proto 串联起来的对象链状结构, 叫做原型链

        原型链作用: 为了对象访问机制服务

  原型链

        从任何一个对象出发, 按照 proto 串联起来的对象链状结构

        为对象访问机制而存在

  使用方法:数组 扩展一个方法

        在: Array.prototype 上

    如果我想给 函数 扩展一个方法

        在: Function.prototype 上

原型

      函数天生自带 prototype 的属性

        存放一些方法, 供这个构造函数的所有实例使用

 constructor 属性(构造器)

        只有函数天生自带的那个 prototype 上有

        表示我是哪一个构造函数所自带的 原型对象

        作用: 判断数据类型

  判断数据类型

        1. typeof

          准确的判断基本数据类型

          缺点: 对于复杂数据类型并不准确

 2. constructor

      利用原型的属性

          利用对象访问机制

  1. instanceof

使用方法: 对象 instanceof 构造函数

  1. Object.prototype.toString.call()

          使用方法: Object.prototype.toString.call(你要检测的数据类型);

了解对象

数据类型的一种

        以键值对的形式存储数据

        因为 proto 和 原型链 可以访问自己没有的属性

for in 循环

        专门遍历对象

        遍历对象身上的所有属性

        遍历对象身上所有的 可枚举 的属性(包括原型链上的所有 可枚举 属性)

          是一种自定义的属性

对象自己的方法

        1. hasOwnProperty()

          查看是不是自己的属性

          使用方法: 对象.hasOwnProperty('你要检测的属性名')

        2. defineProperty() 数据劫持

        一种给对象添加属性的方法

          我可以给一个我设置的属性设置各种各样的行为状态

          使用方法: Object.defineProperty(给哪一个对象添加,  key, {

            添加的设置

          })