zoukankan      html  css  js  c++  java
  • JS中的类Class的总结

    1、虽然ES6类表面上看起来是可以支持正式的面向对象编程,但是实际上它背后使用的仍然是原型和构造函数的概念

    2、类与函数之间的区别

    与函数的定义不同的是,虽然函数声明可以提升,但类的定义不可以提升

    函数受函数作用域限制,而类受块作用域限制

    类表达式的名称是可选的,把类表达式赋值给变量后,可以通过属性取得类表达式的名称字符串,但不能在表达式作用域外部访问这个标识符

    let Person = class PersonName {
         identify() {
             console.log(Person.name, PersonName.name)
         }
    }
    
    let p = new Person()
    
    p.identify()
    
    console.log(Person.name)
    console.log(PersonName)
    

    3、constructor关键字

    constructor关键字用于在类定义块内部创建类的构造函数,方法名constructor会告诉解释器在使用new操作符创建类的新实例时,应该调用这个函数。构造函数的定义不是必须的,不定义构造函数相当于将构造函数定义为空函数。

    4、实例化

    使用new操作符实例化Person的操作等于使用new调用其构造函数。唯一可感知的不同之处就是,Javascript解释器知道使用new和类意味着应该使用constructor函数进行实例化

    使用new调用类的构造函数会执行如下操作

    (1)在内存中创建一个新对象

    (2)这个新对象内部的[[ Prototype ]]指针被赋值为构造函数的prototype属性

      (3) 构造函数内部的this被赋值为这个新对象(即this指向新对象)

    (4)执行构造函数内部的代码(给新对象添加属性)

    (5)如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象

     看看高程上关于对象和原型的部分

    class Animal {}
    
    class Person {
      constructor() {
        console.log('person ctor')
      }
    }
    
    class Vegetable {
      constructor() {
        this.color = 'orange'
      }
    }
    
    let a = new Animal()
    
    let p = new Person()
    
    let v = new Vegetable()
    
    console.log(v.color)

    类实例化时传入的参数会作用构造函数的参数,如果不需要参数,则类名后面的括号也是可选的

    class Person {
      constructor(name) {
        console.log(arguments.length)
        this.name = name || null
      }
    }
    
    let p1 = new Person
    console.log(p1.name)
    
    let p2 = new Person()
    console.log(p2.name)
    
    let p3 = new Person('Jake')
    console.log(p3.name)

    默认情况下,类构造函数会在执行之后返回this对象,构造函数返回的对象会被用作实例化的对象,如果没有什么引用新创建的this对象,那么这个对象会被销毁,不过,如果返回的不是this对象,而是其他对象,那么这个对象不会通过instanceof操作符检测出跟类有关联,因为这个对象的原型指针并没有修改

    class Person {
      constructor(override) {
        this.foo = 'foo'
        if(override) {
          return {
            bar: 'bar'
          }
        }
      }
    }
    
    let p1 = new Person(),
        p2 = new Person(true);
    
    console.log(p1)
    console.log(p1 instanceof Person)
    
    console.log(p2)
    console.log(p2 instanceof Person)

    类构造函数与构造函数的主要区别是:调用类构造函数必须使用new操作符,而普通构造函数如果不使用new调用,那么就会以全局的this(通常是window)作为内部对象

    类通过typeof操作符检测类标识符,表明它是一个函数

    class Person {}
    
    console.log(Person)
    console.log(typeof Person)
    
    
    console.log(Person.prototype)
    console.log(Person === Person.prototype.constructor)

    在类的上下文中,类本身在使用new调用时就会被当成构造函数

    类中定义的constructor方法不会被当作构造函数,在对它使用instanceof操作符时会返回false

    如果在创建实例时直接将类构造函数当成普通构造函数来使用,那么instanceof操作符的返回值会反转

    class Person {}
    
    let p1 = new Person()
    
    console.log(p1.constructor === Person)
    console.log(p1 instanceof Person)
    console.log(p1 instanceof Person.constructor)
    
    let p2 = new Person.constructor()
    
    console.log(p2.constructor === Person)
    console.log(p2 instanceof Person)
    console.log(p2 instanceof Person.constructor)

    5、实例成员

    每个实例都对应一个唯一的成员对象,所有成员都不会在原型上共享

    class Person {
      constructor() {
    
        this.name = new String('Jack')
    
        this.nicknames = ['Jake', 'J-Dog']
      }
    }
    
    let p1 = new Person(), 
        p2 = new Person();
    p1.sayName()
    p2.sayName()
    
    console.log(p1.name === p2.name)
    console.log(p1.sayName === p2.sayName)
    console.log(p1.nicknames === p2.nicknames)

    6、为了在实例间共享方法,类定义语法把在类块中定义的方法作为原型方法

    class Person {
      constructor() {
        // 添加到this的所有内容都会存在于不同的实例上
        this.locate = () => console.log('instance')
    
        // 在类块中定义的所有内容都会定义在类的原型上
        locate() {
          console.log('prototype')
        }
      }
    }

    类定义也支持获取和设置访问器,语法和普通对象一样:

    class Person {
      set name(newName) {
        this.name_ = newName
      }
    
      get name() {
        return this.name_
      }
    }
    
    let p = new Person()
    p.name = 'Jake'
    console.log(p.name)

    7、静态类方法

    静态类成员在类定义中使用static关键字作为前缀

    在静态成员中,this引用类自有约定跟原型成员一样

    静态类方法非常适合作为实例工厂

    8、类的继承

    ES6中原生支持了类继承,虽然使用了新的语法,但是背后使用的还是原型链

    类可以继承类,也可以继承普通的构造函数(保持向后兼容)

    派生类都会通过原型链访问到类和原型上定义的方法

    9、super

    派生类的方法可以通过super关键字引用他们的原型

    关键字只能在派生类中使用,而且仅限于类构造函数、实例方法和静态方法内部

    在类构造函数中使用super可以调用父类构造函数

    10、抽象基类

    11、类混入

  • 相关阅读:
    译:DOM2中的高级事件处理(转)
    Cookbook of QUnit
    URI编码解码和base64
    css截断长文本显示
    内置对象,原生对象和宿主对象
    HTML中的meta(转载)
    iframe编程的一些问题
    自动补全搜索实现
    new的探究
    深入instanceof
  • 原文地址:https://www.cnblogs.com/Roxxane/p/14472127.html
Copyright © 2011-2022 走看看