JavaScript中的Function与class语法糖

当 JavaScript在2015年发布了ES6标准时,引入了一项重要的功能------类(class)。然而,我们必须明确一点:JavaScript本质上仍然是基于原型的面向对象语言,而类只是一种语法糖,用于更方便地创建和组织对象。本文将来讨论ES6中的类和函数。

首先,让我们明确一点:JavaScript没有传统意义上的类。在JS中,一切都是对象,而函数则是一等公民。函数既可以作为普通函数执行,又可以作为构造函数使用。这就是为什么我们常常听到"JavaScript是一门基于原型的面向对象语言"的说法。而类(class)的引入是为了使JavaScript更适合企业级开发,并以更类似于其他大型语言的方式来实现面向对象编程。

类

ES6中引入的类是一种语法糖,它实际上并没有改变JavaScript的原型继承机制 (如果对js的原型还不了解,可以先去看一下这篇文章 JavaScript原型与原型链:理解核心概念,构建强大的前端技能)。类只是一种更简洁、更易读的语法形式,用于定义对象的结构和行为。类的声明方式如下:

javascript 复制代码
class Person {
  constructor(name) {
    this.name = name;
  }

  sayHello() {
    console.log(`Hello, my name is ${this.name}.`);
  }
}

const person = new Person("John"); 
person.sayHello(); // 输出:Hello, my name is John.

上面的代码定义了一个名为Person的类,具有一个构造函数constructor和一个sayHello的方法。构造函数负责实例化对象并初始化其属性,而方法则定义了对象的行为。我们使用 "new" 关键字创建了一个名为 "person" 的类实例,并调用了它的 "sayHello" 方法。我们需要注意的是,这些方法都是定义在类的原型对象上的,而不是实例本身。这意味着所有类的实例共享相同的方法,这样可以节省内存,因为每个实例可以不用单独保存方法。

函数

在ES6之前,我们使用传统的构造函数、原型对象和实例的方式来创建对象。通过构造函数创建实例时,构造函数内部的this指向新创建的实例。原型对象则通过实例的__proto__属性来保持原型关系,而constructor属性告诉实例它是由哪个构造函数创建的。

javascript 复制代码
    function Person(name){
        this.name = name;
    }
    Person.prototype.sayHello = function(){
        return console.log('hello,I am ' + this.name);
    }
    
    const person = new Person("John"); 
    console.log(Person.prototype===person.__proto__); // 输出true
    person.sayHello(); // 输出:Hello, my name is John.
    

这段代码和上面类的那段代码作用是一样的。

当我们遍历一个对象上的属性时,可以发现原型对象上的属性是可遍历的,但constructor属性除外。我们可以使用Object.keys()方法来获取对象上可遍历的属性。我们到浏览器的控制台上使用Object.keys(Person.prototype)可以看到:

而直接打印Person.prototype,则可以看到它上面还有的constructor属性:

为什么说Class是语法糖

实际上,class的底层原理和Function是一样的,我们换到之前类的那段代码,再去控制台打印Person.prototype,可以看到:

它也有原型,也是通过原型继承来实现对象之间的关系。

另一个需要注意的是,类所声明的方法不可被遍历(枚举),我们使用Object.keys(Person.prototype)得到的是空数组。

类声明的方法默认是不可枚举的。这是因为类的方法通常用于定义对象的行为,而不是作为对象的数据属性。为了避免将类方法错误地当作普通属性进行遍历和操作,类方法被设计为不可枚举。

原型继承可以比喻为对象之间的委托关系,一个对象可以通过指向另一个对象作为其原型,从而继承原型对象的属性和方法。

虽然原型继承灵活且功能强大,但使用起来相对复杂,需要手动设置原型链、构造函数等。这导致了代码可读性不高,编写和阅读对象之间关系的代码变得困难。

ES6 引入了 class 关键字,提供了一种更直观、更易理解的方式来定义对象和对象之间的关系。class 通过将对象和继承的概念封装在一个简洁的语法中,使代码结构更清晰、易于维护。

当我们使用 class 声明一个类时,实际上是在底层使用原型继承来实现类的行为。class 的方法会被添加到构造函数的原型对象上,并通过原型链的方式进行继承。

因此,将 class 称为语法糖是指它只是一种更便捷的语法,封装了底层的原型继承机制,使代码更易于理解和编写。虽然它提供了更类似传统面向对象编程语言的语法,但实质上仍然使用原型继承来实现对象之间的关系。

相关推荐
2601_949950631 小时前
练题簿在线免费刷题 从资料整理到考前自测
面试·职场和发展·pdf·word·刷题
福兮说2 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
时间的拾荒人3 小时前
Qt 多线程详解:从 QThread 到实战
开发语言·qt·面试
海绵宝宝转agent3 小时前
MySql高频面试八股开源笔记总结
mysql·面试·开源
郑州光合科技余经理3 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
小呆呆6663 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
凤城老人4 小时前
从 PyQt6 到 Electron:给 Edge TTS 做一个“多角色配音机“的踩坑手记
javascript·typescript·electron
Dovis(誓平步青云)4 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
lsc_blog4 小时前
远程和居家办公的经历,技术简历上怎么摆
面试·职场和发展·重构·pdf·求职招聘
码艺-Alimjan4 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js