了解JavaScript中的类

更新日期: 2019-11-25阅读: 1.7k标签: 

javascript是一种基于原型的语言,javascript中的每个对象都有一个名为[[原型]]的隐藏内部属性,可用于扩展对象属性和方法。

直到最近,勤奋的开发人员使用构造函数来模仿JavaScript中面向对象的设计模式。语言规范ECMAScript 2015(通常称为ES6)引入了JavaScript语言的类。JavaScript中的类实际上并没有提供额外的功能,并且通常被描述为提供原型和继承的“语法糖”,因为它们提供了更清晰,更优雅的语法。由于其他编程语言使用类,因此JavaScript中的类语法使开发人员在语言之间移动变得更加直接。


类是函数:

JavaScript类是一种函数。使用class关键字声明类。我们将使用函数表达式语法初始化函数和类表达式语法来初始化类。

// Initializing a function with a function expression
const x = function() {}
// Initializing a class with a class expression
const y = class {}

我们可以使用object.getprototypeof()方法访问对象的[[原型]]。让我们用它来测试我们创建的空函数。

Object.getPrototypeOf(x);
Output
ƒ () { [native code] }

我们也可以在刚刚创建的类上使用该方法。

Object.getPrototypeOf(y);
Output
ƒ () { [native code] }

用函数和类声明的代码都返回函数[[原型]]。使用原型,任何函数都可以使用new关键字成为构造函数实例。

const x = function() {}
// Initialize a constructor from a functionconst 
constructorFromFunction = new x();
console.log(constructorFromFunction);
Output
x {}
constructor: ƒ ()

这也适用于类。

const y = class {}
// Initialize a constructor from a class
const constructorFromClass = new y();
console.log(constructorFromClass);
Output
y {}
constructor: class

这些原型构造函数示例在其他方面是空的,但是我们可以看到在语法的下面,这两个方法是如何实现相同的最终结果的。


定义一个类

一个构造函数函数是用一些参数初始化的,这些参数将被指定为该函数的属性,并引用该函数本身。按照惯例,标识符的第一个字母将大写。

constructor.js

// Initializing a constructor 
functionfunction Hero(name, level) {
    this.name = name;    
    this.level = level;
    }

当我们将其转换为类语法时,如下所示,我们看到它的结构非常相似。

class.js

// Initializing a class definition
class Hero {
    constructor(name, level) {
        this.name = name;        
        this.level = level;
    }}

我们知道构造器函数通过初始化器的第一个字母大写(可选)和熟悉语法来表示对象蓝图。class关键字以更直接的方式传递函数的目标。

初始化语法的唯一区别是使用class关键字而不是函数,并在constructor()方法中分配属性。


定义方法

构造函数函数的常见做法是将方法直接分配给原型,而不是在初始化过程中,如下面的greet()方法所示。

constructor.js

function Hero(name, level) {
    this.name = name;    
    this.level = level;
}// Adding a method to the constructor
Hero.prototype.greet = function() {
    return `${this.name} says hello.`;
}

对于类,这种语法被简化,方法可以直接添加到类中。

class.js

class Hero {
    constructor(name, level) {        
    this.name = name;        
    this.level = level;
    }    
    // Adding a method to the constructor
    greet() {        
          return `${this.name} says hello.`;
    }
}

让我们看看这些属性和方法的实际应用。我们将使用新关键字创建一个新的英雄实例,并分配一些值。

const hero1 = new Hero('Varg', 1);

如果我们用console.log(hero1)打印出更多关于新对象的信息,我们可以看到更多关于类初始化的细节。

Output
Hero {name: "Varg", level: 1}
__proto__:
  ▶ constructor: class Hero
  ▶ greet: ƒ greet()

我们可以在输出中看到constructor()和greet()函数被应用于hero1的uu proto_uuuu或[[prototype]],而不是直接作为hero1对象上的方法。虽然这在构造构造函数函数时很明显,但在创建类时并不明显。类允许更简单和简洁的语法,但会在过程中牺牲一些清晰度。


扩展类

构造器函数和类的一个优点是,它们可以基于父对象扩展为新的对象蓝图。这可以防止对相似但需要一些额外或更具体功能的对象重复代码。

可以使用call()方法从父级创建新的构造函数函数。在下面的示例中,我们将创建一个更具体的字符类mage,并使用call()将hero的属性分配给它,同时添加一个额外的属性。

constructor.js

// Creating a new constructor from the parent
function Mage(name, level, spell) {
    // Chain constructor with call
    Hero.call(this, name, level);    
    this.spell = spell;
}

此时,我们可以创建一个Mage使用相同属性的新实例,Hero以及我们添加的新属性。

const hero2 = new Mage('Lejon', 2, 'Magic Missile');

发送hero2到控制台,我们可以看到我们已经Mage根据构造函数创建了一个新的。

Output
Mage {name: "Lejon", level: 2, spell: "Magic Missile"}
__proto__:
    ▶ constructor: ƒ Mage(name, level, spell)

对于ES6类,使用super关键字代替call访问父函数。我们将用于extends引用父类。

class.js

// Creating a new class from the parent
class Mage extends Hero {
    constructor(name, level, spell) {
        // Chain constructor with super
        super(name, level);
        // Add a new property
        this.spell = spell;
    }}

现在我们可以以相同的方式创建一个新的Mage实例。

const hero2 = new Mage('Lejon', 2, 'Magic Missile');

我们将打印hero2到控制台并查看输出。

Output
Mage {name: "Lejon", level: 2, spell: "Magic Missile"}
__proto__: Hero
    ▶ constructor: class Mage

输出几乎完全相同,除了在类构造中[[Prototype]]链接到父类,在本例中是Hero。

下面是初始化、添加方法以及构造函数函数和类继承的整个过程的并行比较。

constructor.js

function Hero(name, level) {
    this.name = name;    
    this.level = level;
}// Adding a method to the constructor
Hero.prototype.greet = function() {
    return `${this.name} says hello.`;
}// Creating a new constructor from the parent
function Mage(name, level, spell) {
    // Chain constructor with call
    Hero.call(this, name, level);    
    this.spell = spell;
}

class.js

// Initializing a class
class Hero {
    constructor(name, level) {        
    this.name = name;        
    this.level = level;
    }    
    // Adding a method to the constructor
    greet() {
            return `${this.name} says hello.`;
    }
}
// Creating a new class from the parent
class Mage extends Hero {
    constructor(name, level, spell) {        
        // Chain constructor with super
        super(name, level);
         // Add a new property
        this.spell = spell;
    }
}

虽然语法完全不同,但两种方法的基本结果几乎相同。 类为我们提供了一种更简洁的方法来创建对象蓝图,构造函数更准确地描述了引擎盖下发生的事情。


结论

在本教程中,我们了解了JavaScript构造函数和ES6类之间的相似点和不同点。类和构造函数都模仿面向对象的继承模型到JavaScript,这是一种基于原型的继承语言。

理解原型继承对于成为有效的JavaScript开发人员至关重要。熟悉类非常有用,因为像react这样的流行JavaScript库经常使用class语法。

链接: https://www.fly63.com/article/detial/7701

es6之js的类

ES6 的类让 JS 中的继承变得更简单,因此对于你已从其他语言学习到的类知识,你无须将其丢弃。 ES6 的类起初是作为 ES5 传统继承模型的语法糖,但添加了许多特性来减少错误。

利用 es6 new.target 来对模拟抽象类

最近在使用 Symbol 来做为唯一值,发现 Symbol 无法进行 new 操作,只能当作函数使用,只要进行了new 就会发生类型错误,在不考虑底层实现的情况下,在代码层面是否能够实现一个函数只可以进行调用而不可以进行 new 操作呢?

Js即将加入私有字段和私有方法

尽管 JavaScript 在 2015 年就有了类,但仍然没有私有字段和私有方法。由于 TC39 委员会 内部存在分歧,这些功能在最初版本中被取消。有三个规范草案打算在不久的将来将这些功能引入到 JavaScript 类中。

ts中类的定义

类里面的修饰符 typescript里面定义属性的时候给我们提供了 三种修饰符public :公有 在当前类里面、 子类 、类外面都可以访问,protected:保护类型 在当前类里面、子类里面可以访问 ,在类外部没法访问

创建Vue类的过程

构造函数、全局配置对象、默认options配置、比如 vue-router 就会注册这个回调,因此会每一个组件继承,前面提到了,默认组件有三个 `KeepAlive`,`transition`, `transitionGroup`

javascript中uber实现子类访问父类成员

上面代码通过实例化子类和父类,分别调用toString()实现了继承的关系。这个时候有这样的需求;不实例化父类,直接通过子类完完整整的调用父类的方法或属性。

如何在Vue中动态添加类名

能够向组件添加动态类名是非常强大的功能。它使我们可以更轻松地编写自定义主题,根据组件的状态添加类,还可以编写依赖于样式的组件的不同变体。添加动态类名与在组件中添加 prop :一样简单。

javascript如何定义类?

JavaScript中没有类或接口的概念,即不能直接定义抽象的类,也不能直接实现继承。不过,为了编程的方便,我们可以在JavaScript中模拟类和继承的行为。

JS一些类实现方式的性能研究

这再次证明了JS的写法很灵活(举个反面的例子,如Python,其哲学原则是one way to go!)。这里整理一下,研究一下各种实现的性能问题

在Vue中如何避免在动态绑定类出现空类的情况?

传递空字符串,这可能会导致 DOM 输出中的类为空。 在三元运算符中,我们可以返回null,这可以确保 DOM 中没有空类

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!