2023-02-01 JS 自己总结的面向对象,以及this

2023-01-31  本文已影响0人  本泽锅

这一段时间都在回顾和总结之前JS中一些比较重要的内容,再次写个日记,记录下

面向对象的三大特征:
1.封装
2.继承
3.多态

封装
封装是指创建一个对象集中保存一个事物的属性与功能:
封装对象有三种方式:
\color{red}{第一种 }:直接用{}

    var obj = {}
    var obj1 = {
      name: '本泽锅',
      foo: function() {
        console.log(`I'm ${name}`)
        //这里直接用name会报错,Uncaught ReferenceError: name is not defined
        //原因就是对象的{}不是作用域,函数foo的作用域链只有自己和顶层的window,显然会报错
        //解决方法:
         console.log(`I'm ${this.name}`)
        //这里就是 this的第一种情况:在普通函数中的this,指向的是调用当前函数的.前的对象
      }
    }
    console.log('obj', obj)
    console.log('obj1', obj1)

\color{red}{ this的第一种情况:在普通函数中的this,指向的是调用当前函数的.前的对象 }

\color{red}{第二种 }:通过new关键词新建对象

    var obj = new Object()
    console.log('obj',obj)
    var obj1 = new Object()
    obj1.name = '本泽锅'

\color{red}{第三种 }:通过构造函数的方式

     function Student (name,foo) { 
      //将来要加入到新对象中的属性和方法
        this.name = name
        this.foo= foo
        //这里就是 this的第二种情况:在构造函数中的this,指向的是new创建的新对象
    }
 
    //  实例化1
    var obj = new Student()
    console.log('obj',obj)
    //  实例化2
    var obj1 = new Student('本泽锅',function (){
    })
    console.log('obj1',obj1)
    obj1.foo()
      
    总结: 通过构造函数的方式创建对象  一共干了4件事
    1.创建了一个新的空对象。
    2.让子对象继承构造函数的原型对象。(将子对象的隐式原型__proto__指向创建该构造函数的显示原型prototype上)
    3.调用构造函数,将this替换为新对象,通过强行赋值的方式为新对象添加属性和方法。
    4.返回新对象的地址值。

\color{red}{ this的第二种情况:在构造函数中的this,指向的是new创建的新对象 }

继承
继承是父对象中的成员,子对象无需重复创建,就可以直接使用。
js中的几种都是通过原型对象来实现的。
原型对象:替所有子对象集中保存共有属性和方法的父对象。

概念:每一个构造函数都有一个显示原型ptototype.
每一个对象都有一个隐式原型proto,对象的隐式原型指向创建该构造函数的显示原型

当我们通过构造函数实例化一个对象的时候,就会自动将子对象的隐式原型指向创建该构造函数的显示原型,这样就达到了继承的目的。

原型执行规则
当我们获取对象的属性或者方法时,首先在自身查找,如果有的话就使用,如果没有的话,就自动去隐示原型proto中去查找,而隐示原型会指向创建该对象构造函数的显示原型prototype去查找
原型链
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的proto隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的proto中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链,直到找到顶端Object的显示原型prototype,而Object的显示原型prototype中隐示原型proto为null,这样就停止了。

向原型对象中添加共有属性和方法:

     function Student (name,foo) { 
        this.name = name
        this.foo= foo
    }
    //只能通过强行赋值的方法
    Student.prototype.location= '武汉'
    Student.prototype.study=function(){
    console.log(this.name,'student')
//这里就是 this的第三种情况:原型对象中共有方法里的this,将来调用这个共有方法的.前的那个子对象
}

\color{red}{ this的第三种情况:原型对象中共有方法里的this,将来调用这个共有方法的.前的那个子对象}

多态:
同一个函数,在不同情况下表现出的不同的状态。

面向对象小结:
1、封装: 创建对象,2种:
如果只创建一个对象: {} 如果反复创建多个相同结构的对象: 构造函数
2、继承: 所有子对象共用的属性值和方法,都要 放在构造函数的原型对象中
3、多态: 重写: 只要觉得从父对象继承来的成员 不要用,都在子对象中重写同名成员

this的几种情况:

    1. obj.fun() this->.前的obj对象
    2. new构造函数() this->new正在创建的新对象 
    3. 构造函数.prototype.fun=function(){}
        因为将来原型对象中的方法,都是”子对象.fun()”方式调用。 所以,this->将来调用这个fun函数的.前的某个子对象
    4. fun()、匿名函数自调和回调函数中的 this->window
    5. button.onclick=function(){}或button.addEventListener(“click”,function(){...}) DOM事件处理函数里的
        this-> 当前正在出发事件的.前的DOM元素对象。
    6. 箭头函数中的this->当前函数之外最近的作用域中的this
       - 几乎所有匿名函数都可用箭头函数简化
        - 箭头函数是对大多数匿名函数的简写
      箭头函数底层相当于.bind()  永久绑定外部this
    7. 改变this的指向
         其实,对于this,我们不一定逆来顺受
          • - 可用call或apply,临时替换一次函数中的this
          • - 可用bind,永久替换函数中的this
          总结:
          • a. 只在一次调用函数时,临时替换一次this: call
          • b. 既要替换一次this,又要拆散数组再传参: apply
          • c. 创建新函数副本,并永久绑定this: bind
上一篇下一篇

猜你喜欢

热点阅读