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

相关推荐
如若12316 分钟前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~1 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语1 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport1 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg1 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww1 小时前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest
m0_748254881 小时前
vue+elementui实现下拉表格多选+搜索+分页+回显+全选2.0
前端·vue.js·elementui
ThisIsClark2 小时前
【后端面试总结】深入解析进程和线程的区别
java·jvm·面试
星就前端叭2 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
m0_748234522 小时前
前端Vue3字体优化三部曲(webFont、font-spider、spa-font-spider-webpack-plugin)
前端·webpack·node.js