美文网首页
第十九章 Class的基本语法

第十九章 Class的基本语法

作者: A郑家庆 | 来源:发表于2019-01-06 12:17 被阅读0次

简介

  Javascript语言的传统方法是通过构造函数定义并生成新对象。

    function Point (x, y) {
        this.x = x
        this.y = y
    }
    Point.prototype.toString = function () {
        return '(' + this.x + ',' + this.y +')'
    }
    let p = new Point(1, 2)

  上面这种写法与传统的面向对象语言(c++和java)的写法差异很大,ES6提供了更接近传统语言的写法,引入了Class(类)这个概念作为对象的模版。通过class关键字可以定义类。
  基本上ES6中的class可以看作ES5构造函数的语法糖,它的绝大部分功能ES5原型都可以实现,新的class写法只是让对象原型的写法更加清晰,更像面向对象编程的语法而已。上面的代码可以用ES6改写成这样:

    class Point { 
        constructor (x, y) {
            this.x = x
            this.y = y
        }
        toString () {
            return '(' + this.x + ',' + this.y +')'
        }
    }

  从上面代码可以看出,ES5构造函数Point对应ES6的Point类的构造方法。

class类型的方法不需要用逗号分隔。

ES6的类完全可以看作构造函数的另一种写法。

class Point {
      //
}
typeof Point    // 'function'
Point === Point.protoytpe.constructor  // true

上面代码表明,类的数据类型就是函数,类本身就指向构造函数。使用的时候也是直接对类使用new命令,跟构造函数的用法完全一致。

    class Bar {
        doStuff () {
            console.log('stuff')
        }
    }
    let b = new Bar()
    b.doStuff()  // stuff

构造函数的prototype属性在ES6的类上继续存在。事实上类的所有方法都定义在类的prototype属性上。

class Point {
    constructor () {
        // ...
    }
    toString () {
       // ...
    }
    toValue () {
      // ...
    }
}
// 等同于
Point.prototype = {
    constructor () {},
    toString () {},
    toValue () {}
}

在类的实例上调用方法,其实就是调用原型上的方法。由于类的方法(除了constructor以外)都定义在prototype对象上,所以类的新方法可以添加在prototype。
另外,类的内部定义的所有方法都是不可枚举的。

class Point {
    constructor () {
        // ...
    }
    toString () {
       // ...
    }
}
Object.keys(Point.prototype)   // []
Object.getOwnPropertyNames(Point.prototype) // ['constructor', 'toString']

let Point = function (x, y) {
    // ...
}
Point.prototype.toString = function () {
   // ...
}
Object.keys(Point.prototype)   // ['toString']
Object.getOwnPropertyNames(Point.prototype) // ['constructor', 'toString']

上面代码中,toString方法是Point类内部定义的方法,它是不可枚举的。这一点与ES5的行为不一致。
类的属性名可以是表达式,也可以是变量。

let methodNames = 'getArea'
class Square {
     [methodNames] () {
         // ...
     }
}

constructor方法

  constructor方法是类的默认方法,通过new命令生成对象实例时自动调用该方法。一个类必须有constructor方法,如果没有显示定义,一个空的constructor方法会被默认添加。

class Point {}
// 等同于
class Point {
    constructor () {}
}

constructor方法默认返回实例对象(即this),不过完全可以指定返回另外一个对象。

class Foo {
     constructor () {
         return Object.creat(null)
     }
}
new Foo() instance Foo  // false

上面代码中,constructor函数返回一个全新的对象,结果导致实例对象不是Foo类的实例。类必须使用new来调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行。

类的实例对象

与ES5一样,实例的属性除非显示定义在其本身(即this对象)上,否则都是定义在原型(即class)上。

    class Point { 
        constructor (x, y) {
            this.x = x
            this.y = y
        }
        toString () {
            return '(' + this.x + ',' + this.y +')'
        }
    }
   let point = new Point(2, 3)
   point.toString()  // (2, 3)
   point.hasOwnProperty('x')   // true
   point.hasOwnProperty('y')   // true
   point.hasOwnProperty('toString')   // false
   point.__proto__.hasOwnProperty('toString')   // true

上面代码中,x和y都是实例对象point自身的属性(因为定义在this变量上),所以hasOwnProperty返回true,而toString是原型的属性,所以返回false。这些都与ES5行为保持一致。
与ES5一样,类的所有实例共享一个原型对象。

let p1 = new Point(2, 3)
let p2 = new Point(1, 1)
p1.__proto === p2.__proto__  
// true
p1.__proto__.printName = function () {return 'oops'}
let p3 = new Point(4, 2)
p3.printName()   // oops

上面代码显示p1、p2、p3都是公用一个类,所以在p1上添加了一个方法在p3上也可以调用。

Class表达式

与函数一样,Class也可以使用表达式的形式定义。

const MyClass = class Me {
     getClassName () {
         return Me.name
     }
}

这个类的名字是myClass而不是Me,Me只在Class内部代码可用,指代当前类。

let inst = new MyClass()
inst.getClassName()  // Me
Me.name   // 报错

上面代码表示,Me只在Class内部有定义。如果Class内部没有用到也可以省略Me。

不存在变量提升

Class类跟普通函数不同之处还在于,前者没有变量提升,后者有。

总结:构造函数和类的异同
相同点:ES5中是在构造函数的原型上定义方法,这样子实例就会继承构造函数的所有方法,ES6是在类的原型上定义方法,实例也会继承类的所有方法,类可以看成是构造函数的语法糖。
不同点:写法不同,构造函数的方法需要写在prototype上,类省略了prototype,但是定义的方法还是在prototype上。
属性枚举:构造函数定义的方法是可枚举的,类定义的方法都是不可枚举的。
调用:构造函数可以不用new调用,但是类必须要用new调用,否则报错。
ES6的类本质上是ES5的构造函数的一层包装,所以函数的许多特性都被Class继承,也可以理解为实例的原型对象

相关文章

  • 第十九章 Class的基本语法

    简介   Javascript语言的传统方法是通过构造函数定义并生成新对象。   上面这种写法与传统的面向对象语言...

  • 第3章 ES6类(Class)使用

    目标 Class基本语法 constructor方法 类的实例对象 1、Class基本语法js传统创建新对象的方法...

  • 第3章 ES6类(Class)使用

    目标 Class基本语法 constructor方法 类的实例对象 1、Class基本语法 js传统创建新对象的方...

  • class 基本语法

    1.简介 JavaScript 语言中,生成实例对象的传统方法是通过构造函数。下面是一个例子。 上面这种写法跟传统...

  • Class 的基本语法

    简介 严格模式 constructor 方法 类的实例对象 Class 表达式 不存在变量提升 私有方法和私有属性...

  • Class 的基本语法

    传统一个函数的申明和方法建立,如下所示: 上面这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大,...

  • Class的基本语法

    一. 简介 1 类的由来 es5js语言中生成实例对象的方法通过 构造函数 ES6 提供了更接近传统语言的写法,引...

  • Class 的基本语法

    一、简介 JavaScript 语言的传统方法是通过构造函数定义并生成新对象。 ES6 提供了更接近传统语言的写法...

  • Class的基本语法(笔记)

    js与es6对比 1.js中没有类(class)这个概念,通过构造函数的方式实例化对象。 2.es6中,引入类这个...

  • ES6之class

    class基本语法: 1.实质: ​ class只是一个语法糖,类的所有方法都定义在类的prototype...

网友评论

      本文标题:第十九章 Class的基本语法

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