面向对象进阶

对象

概念理解

  • 什么是对象,其实就是一种类型,即引用类型。而对象的值就是引用类型的实例。在ECMAScript中引用类型是一种数据结构,用于将数据和功能组织在一起,他常常被称为类。

  • 万物皆对象,除了数字,字符,布尔这种绝对值以外的所有部分都是对象,
    对象是类的实例化体现,类是对象的抽象体现。

  • 每个对象都有自己的属性和方法

  • 原型

    • obj.proto

创建对象

  • new obj= new Object()

  • new obj = {}

    • 字面量
  • new obj = Object.create()

    • 函数构造法

new Object()

  • obj[属性]=属性值

  • obj[方法]=方法函数

  • var arr = new Object([])

    • 创建数组,在javascript中数组不是单独的类型,它是由对象扩展出来的,因此,可以使用这种形式来建立数组。
    • 一般不用这种方式创建数组和对象,会形成两层嵌套循环

原型链__proto__.__proto__⭐

  • 与生俱来的方法和属性就是原型链上的方法和属性

  • 实例化之后尝试的,属于后天形成的,不在原型链上

  • 任何对象都是继承对象原型

    • 万物皆对象

      • 5种(string,number,boolean,undefined,null)基本类型实际也是对象,特殊处理存在栈中,但是调用需要去堆中找到该字符窜字符类型的方法并执行
  • 解决重绘

    • 1.同一时间集中起来重绘
    • 2.预先处理数据,能不重绘的就不重绘
  • 原型链的创建

    • var o = {a:1}
    • var o1 = Object.create(o);
    • 以o作为原型链创建o1
  • 属性

    • 原型链上的属性

      • 不允许直接改变原型链上的属性
    • 获取

      • 当设置对象的属性时,直接设置的是对象自身属性(对象属性);
      • 如果获取时,首先查看该对象有没有这个名称的对象属性,如果有直接返回这个属性值
      • 若果没有,直接继续向下查找紧邻的原型链中的属性是否具有该属性名,查找到距离该对象最近的原型链中的属性名后返回其值

解构

  • o4={…o1,…o2,…o3}
  • 将o1,o2,o3的所有属性解构产生新对象赋值给了o4

属性创建

  • Object.delete

    • 删除对象的属性
    • delete obj.a
  • Object.assign()

    • 将一个或者多个对象中可枚举属性复制到第一个参数对象数中,
    • 如果后面的对象属性与前面的对象属性相同时,则会覆盖前面的对象属性
    • 原对象中增加复制的属性,引用地址不改变
    • 继承属性和不可枚举的属性是不能被拷贝的
  • Object.defineProperty(对象,属性名,该属性的描述对象)

    Object.defineProperty(obj, “a”, {
    configurable: true,//该属性是否可以删除,并且该属性的描述对象是否可以更改
    enumerable: true,//该属性是否可以枚举
    writable: true,//该属性是否可写(不是只读)
    value: 10,//该属性的值
    });
    详细定义对象的属性

    • configurable: true,

      • 该属性是否可以删除,并且该属性的描述对象是否可以更改
      • 省略时默认值为false
    • enumerable: true,

      • 该属性是否可以枚举

        • 不可枚举的属性

          • 不能复制

            • var o=Object.assign({},obj);
            • var o={…obj};
    • writable: true,

      • 该属性是否可写(不是只读)
    • value: 10,

      • 该属性的值
  • Object.defineProperties(obj, props)

    给对象定义属性值

    Object.defineProperties(对象,{
    “属性名”:{
    value:属性值,
    writable:布尔值
    }
    })

    • 属性名必须是字符串,value后面的内容是属性的值,writable是该属性是否可写。
    • ES6的类里面没有常量
  • Object.freeze(arr)

    • 冻结对象,不能修改该对象的所有属性,不能删除所有属性
  • Object.getOwnPropertyNames(obj)

    • 获取对象的所有对象属性名
    • 获取对象下所有属性的名称,并返回一个数组,
    • 该数组的内容就是这些属性名,该数组对元素是 obj 自身拥有的枚举或不可枚举属性名称字符串。
  • Object.getOwnPropertyDescriptor(obj,属性名)

    • 获取对象属性的描述对象
  • Object.is(a,b)

    • 类似于===

      • 和===不同在于 NaN判断NaN是相同的
  • Object.isExtensible(obj)

    • 不可以增加新属性
    • 是否是可扩展
  • Object.isFrozen(obj)

    • 判断对象是否冻结
  • obj.hasOwnProperty(“e”)⭐

    • in也可以判断属性的有无
    • 对象原型链上的属性不是它的属性
    • 当前对象的对象属性,原型链属性不属于范围
  • o.isPrototypeOf(o2)⭐

    Box.isPrototypeOf(Ball)
    //Ball的父类是否有Box类
    Box.isPrototypeOf(b.constructor)
    //b对象的父类中有没有Box类
    HTMLElement.isPrototypeOf(div.constructor)
    //是不是HTML标签

    • o是不是在o2的原型链上
    • o2的父类中有没有o
  • obj.propertyIsEnumerable(“b”)

    • 查询属性是否是不可枚举属性
  • b instanceof Box⭐

    • b是不是box类别

    • 等价于b.constructor===Box

    • 判断是否为空

      • b instanceof Object
      • 结果为false
    • b.constructor===Object 报错

    • 继承不能

  • 空和undefined区别

    • index in arr
    • arr.hasOwnProperty(index)
    • 空对象不存在constructor

深复制⭐⭐⭐

 var obj={
              a:1,
              b:2,
              c:[1,2,3],
              z:document.createElement("div"),
              d:{
                  e:new Date(),
                  f:/a/g,
                  g:function(s){
                      console.log(s);
                  },
                  h:{
  
                  }
              }
          }
          Object.defineProperties(obj.d.h,{
              i:{
                  value:10
              },
              j:{
                  configurable:true,
                  value:[1,2,3,4]
              },
              k:{
                  writable:true,
                  value:{
                      l:{},
                      m:"abcde",
                      n:true,
                      o:[1,2,3]
                  }
              }
          })
  
          Object.defineProperties(obj.d.h.k.l,{
              p:{
                  value:function(){
                      console.log("p")
                  }
              },
              q:{
                  value:{
                      r:{a:1},
                      j:{b:2}
                  }
              }
          });
  • 代码
  function cloneObj(source,target){
              if(target==undefined) target={};
              var names=Object.getOwnPropertyNames(source);
              for(var i=0;i<names.length;i++){
                  var desc=Object.getOwnPropertyDescriptor(source,names[i]);
                  if(typeof desc.value==="object" && desc.value!==null){
                      var obj;
                     switch(true){
                         case desc.value.constructor===Date:
                         obj=new Date(desc.value.toString());
                         break;
                         case desc.value.constructor===RegExp:
                         obj=new RegExp(desc.value.source,desc.value.flags);
                         break;
                         case HTMLElement.isPrototypeOf(desc.value.constructor):
                         obj=document.createElement(desc.value.nodeName);
                         break;
                         default:
                         obj=new desc.value.constructor()
                     }
                      Object.defineProperty(target,names[i],{
                          enumerable:desc.enumerable,
                          writable:desc.writable,
                          configurable:desc.configurable,
                          value:obj
                      });
                      cloneObj(desc.value,obj);
                  }else{
                      Object.defineProperty(target,names[i],desc)
                  } 
              }
              return target;
          }

函数执行

fn()

  • this =>window

自执行函数

apply()

  • fn.apply(obj)
  • apply只有两个参数,第一个参数是this指向的对象,第二个参数是函数所需的所有参数的数组,列表

call()

  • fn.call(obj)
  • 第一个参数是函数中this指向的对象,后面会按顺序带入参数

bind()

红黄绿灯

 var id;
      function setLight() {
        arguments[0](arguments[1], arguments[2]);
      }
      
      function showLight(fn,fn2){
          clearTimeout(id);
            console.log(this.toString());
            id = setTimeout(fn, 2000, fn2, arguments.callee.bind(this));
      }
      setLight(showLight.bind("红"),showLight.bind("黄"),showLight.bind("绿"));
  • 改变this指向,并封装起来,等待执行
  • 通过bind可以对于回调函数传参,this就是bind绑定的内容

this指向⭐⭐⭐

严格模式 “use strict”;

  • ES5严格模式,ES6,全局中this仍然指向window,函数中this指向undefined

非严格模式

  • ES5非严格模式 全局中this和函数中this都指向window

对象中的this

var obj={
            a:1,
            b:function(){
                // console.log(this);//this不会因为变量引用改变而改变
                // this指向当前对象自身obj
                // console.log(obj.a);//变量会发生引用改变
            },
            c:this.a
            // this指向对象外this的指向
            // 对象没有创建完成时,this还没有生成,this就指向对象外this的指向
        }
  • 对象没有创建完成时,this还没有生成,this就指向对象外this的指向

回调函数

  var obj = {
        a: function () {
            console.log(this,"____");
            var self=this;
            function fn1(fn) {
                 fn();
                 arguments[0]();
                fn.call(self);
            }
            function fn2() {
                console.log(this);//window 回调函数中
                1、如果直接指向的回调函数,this指向最外层window
                2、如果通过arguments直接使用参数指向函数,this则指向执行当前函数的arguments
               3、如果回调函数通过call,apply,bind重新指向了新的对象时,this就是指向新对象

            }
            fn1(fn2);
        },
      };

      obj.a(); */
  • 1、如果直接指向的回调函数,this指向最外层window
  • 2、如果通过arguments直接使用参数指向函数,this则指向执行当前函数的arguments
  • 3、如果回调函数通过call,apply,bind重新指向了新的对象时,this就是指向新对象

事件中this

var obj={
          b:1,
          a:function(){
            //   特殊的回调函数
              document.addEventListener("click",this.clickHandler);
          },
          clickHandler:function(e){
                console.log(this);//事件侦听的对象 e.currentTarget
          } 

this指向document

  • IE 8 attachEvent侦听事件时,this指向window

ES6类

 class Box{
          static _instance;
           constructor(){
               console.log(this);//指向被实例化的对象
           }
           static getInstance(){
               if(!Box._instance){
                  Box._instance=new Box();
              }
               return Box._instance;
           }
           play(){
              console.log(this,"|");//指向被实例化的对象
          }
           static run(){
              // console.log(this);
              console.log(this===Box,"____");
               // this就是当前类名也是构造函数
               // 任何的静态方法中this都是当前类
               // 静态方法中无法获取到实例化对象的this的
             return this;
         }

          static plays(){
              // this.getInstance().play();
             var o=this.getInstance();
               var o1=this.getInstance();
              console.log(o===o1);
          }
       }

      // var b=new Box();//会执行构造函数,这是构造函数中this就是这个b对象
       // b.play();//b对象下的方法play,因此play方法中this被指向b,谁执行play,this指向谁
      // console.log(Box.run()===b);//false
       // console.log(Box.run()===b.constructor);//true
  • constructor()中的this指向被实例化的对象

  • 静态方法中

    • 任何的静态方法中this都是当前类
    • 静态方法中无法获取到实例化对象的this的
    • this就是当前类名也是构造函数

ES5 面向对象中的this

  • constructor()中的this指向被实例化的对象

箭头函数

  var obj = {
         a: function () {
        setTimeout(() => {
            console.log(this);//this是箭头函数外this的指向
             // 上下文环境中this的指向
           }, 2000);
         },
         };
       obj.a();
  • this是箭头函数外this的指向
  • 上下文环境中this的指向

call apply bind

  • this指向obj
  • 数组隐式类型转换为字符串,会在每个元素间添加一个逗号
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值