JS开发者应知的100个概念-中

这一部分是系列内容中的第二部分-中。该系列的上部分内容在:

juejin.cn/post/730226...

接续上一部分,本部分的内容如下:

▢ 0x1F: Function, 函数

函数,是一种程序语言体系提供的规范化代码和操作组织的语法结构,通常用于完成某项特别的信息处理和操作。函数通常由函数名、参数、函数体和返回值等要素组成。设计和实现函数的目的是程序的模块化,功能的封装和抽象,方便复用和集成,利用开发组织、维护和扩展等等。

▢ 0x20: Function Definition, 函数定义

一个函数的定义,通常由函数的名称,返回数据类型,参数列表(名称、类型),内部操作代码,返回值定义等要素组成。

各种编程语言中,函数的定义和形式可能会略有差异,但其基本结构和目的,其实都是类似的,就是定义一段相对封闭的代码,可以使用相同的处理模式,来对输出参数进行处理,并返回处理结果。

▢ 0x21: Input Params, 输入参数

在函数的应用中,使用输入参数变量有很多好处。首先是提高了函数的可复用性,可以方便解决一类问题而不是一个问题。其他的好处还包括信息处理过程和逻辑的封装,通过参数规范输入提高安全性,程序的模块化和业务解耦,利于程序维护等等。

js的输入参数的支持功能非常强大,有空参数、单一参数、多个参数、可变参数列表、构造参数、默认参数值等等,大大方便了开发工作。

▢ 0x22: Return Value, 返回值

使用函数,可以使用return关键字,指定一个函数执行的返回值给调用的语句,并可以将此值赋予其他变量。配合函数输入参数,使用返回值可以清晰的划分和体现输入-处理-输出的标准冯诺伊曼计算结构。

▢ 0x23: Function Expression, 函数表达式

可以使用类似常量声明的方式,来定义函数,称为函数表达式。常量名称就是函数名称。JS中认为函数也是一种变量,可以作为参数在另一个函数中使用(如回调)。

▢ 0x24: Higher-Ordered Functions, 高层级函数

函数可以作为输入参数,在调用时使用,达到函数调用层级嵌套的效果。这时作为调用者的函数,相对于作为参数的函数(变量),就是更高层级的函数。

▢ 0x25: Closure, 闭包

闭包是JavaScript中一个很重要的概念,指的是可以访问其他函数内部变量的函数。一般在函数嵌套的场景下,闭包函数可以访问和使用其所在函数但非闭包函数内部的变量。

使用闭包函数可以简化函数调用,相当于扩展了变量的使用到闭包函数当中。但也要注意不用滥用,容易导致内存泄露的问题。

▢ 0x26: Call Stack, 调用栈

对于复杂的多个函数调用执行的场景,计算机系统通常使用栈(先进后出)的方式,来组织调用的函数和参数数据。这是计算机底层程序的运行方式,和所使用的语言和系统关系不大。

▢ 0x27: Heap, 堆

堆是程序的一个内存空间。对和栈是独立的内存空间,寻址方式也可能有差别。一般认为,除了函数和参数,其他的对象性的变量,程序会分配堆内存来存储和处理。

▢ 0x28: this, 当前对象

this关键字,用于指代当前所在的对象实例。this成为一个逻辑化的变量,可以简化代码编写和移植。

需要注意的是,对于箭头和匿名函数,this所指并不是函数变量,而是其调用者。

▢ 0x29: Global/Window, 全局/窗口

任何一个js程序,在启动和运行的时候,都有一个默认的变量对象,称为全局变量,这个变量在js的任何函数中,都可以直接使用。在nodejs环境中,这个变量的名称为global(图);在浏览器环境中,由于js总是由某一个页面加载和启动,它的全局变量就是启动程序的页面,就是window窗口。

▢ 0x2A: Bind, 绑定

笔者自己觉得对这个概念的理解可能也不是那么透彻。下面尝试着理解和描述一下。

bind是一个函数的原生方法,其语法和参数是bind(thisArg,[,arg1[,...]]),返回值是一个新的函数,它执行时会以一定的规则调用原绑定函数。其中,thisArg可能(因为也可以传null或者对象实例)改变调用时this的指向;arg会 作为实参插入原型函数的参数之前。

▢ 0x2B: Arrow Function, 箭头函数

JS可以使用箭头函数的声明方式,来声明和定义一个匿名函数或者函数变量。显然,相比经典的函数声明方法,箭头函数更加简单直观。

▢ 0x2C: Anonymous, 匿名函数

有些函数,是"临时性"或者即时使用的,不需要声明和定义表示。匿名函数可以简化这种情况下的代码编写。JS使用匿名函数的场合很多,如普遍使用回调模式。匿名函数也被称为箭头函数或者lambda函数。

和普通函数相比,匿名函数只能直接调用,不能提升只能在定义后使用,不能引用this代指匿名函数对象(不知道为何有这个限制)。

▢ 0x2D: Passed By Value, 参数传值

当使用基本数据类型的变量作为函数调用的参数时,系统会将这个值复制后使用。这时参数传递的是参数值本身。

▢ 0x2E: Passed By Reference, 参数传引用

当使用对象数据类型的变量作为函数调用的参数时,系统不会复制对象,而直接引用这个对象,参数传递的是这个引用。这时,如果要修改对象的属性或者重新赋值,可能会影响到原来的值。

▢ 0x2F: Object Literal, 对象字面量

对象字面量是JavaScript中表示和创建对象的一种简洁语法。使用它可以不需要通过new关键字调用构造函数方便地创建一个对象。使用对象字面量,可以不基于类来创造对象。

Object Literal的形式很像JSON,但是不使用字符串而是变量作为键字,同时也是对象的属性名。并且,它允许属性是函数。这个中文译法太抽象,其实看一个例子就很好理解:

js 复制代码
   // 创建对象 
   let p1 = { 
       id:1, 
       name: "John", 
       say: function(){ console.log(this.name) + " Saying...") }
   };
   
   // 执行方法
   p1.say();

▢ 0x30: Object Constructor, 对象构造

对象构造,是OOP规范中,基于类创建实例的标准方式。对象构造是标准类语法,需要先定义一个类,然后使用new关键字和参数,调用构造函数来创建类对象实例。

和对象字面量相比,对象构造更接近OOP的规范,也可以配合原型链等实现继承等特性。

▢ 0x31: Properties, 对象的属性

在OOP中,对象属性用于描述某个对象的特征和值。可以使用对象+特征名称的方式来方便的访问不同的对象实例的对应特征值。

在JS中,对象的属性可以直接在实例上定义,也可以继承自原型链或者类。有些属性的用途比较简单可以进行遍历也枚举,有些属性特别是来自原型的由系统保留,不能简单的遍历。

▢ 0x32: Prototype Chain, 原型链

原型链是JavaScript中实现继承的一种机制。在JS定义中,所有对象都从一个原型对象(Prototype)继承属性和方法,并且这个原型对象也有其原型,一直到基本对象({}),从而构成原型链。当试图访问一个对象属性时,如果对象自身不存在该属性,JS引擎会尝试在原型链上查找该属性。图为典型的js原型链。

js的原型链有一些自己的特点,和java语言,标准严格的完全基于原型对象的继承关系好像还是有一些不同。

▢ 0x33: Inheritance, 继承

继承,是OOP编程的一个重要概念。它的基本思想是,基于现有的类(父类),可以创建新的类(子类),这些类可以继承其父类的一些属性和方法,并且进行扩展。子类可以添加新的属性和方法,也可以直接使用或者重写父类的方法。一般情况下,类也可以多级继承。

这样可以实现代码的重用,减少额外的开发工作,并且保证程序在一定程度上的一致性。合理设计的类继承可以有效的封装代码和逻辑,提高开发过程的安全性。

OOP继承是一个非常强大而有用的特性,它建立了类之间的关系,使得代码可复用和扩展性都得到增强。但需要适当使用,避免继承链过深造成的复杂度。

▢ 0x34: OOP, Object Oriented Programming,面向对象编程

面向对象编程是一种编程范式,它将真实世界里的事物抽象为程序界面的对象,然后通过对对象的操作来完成程序的设计。其特点和核心主要包括封装(Encapsulation),继承(Inheritance),多态(Polymorphism),抽象(Abstraction)等。图为经典OOP要素和结构示例。

OOP能够使程序和代码更加直观清晰,有利于开发组织、维护和协作,但过度也会增加系统的复杂性。主流的编程语言和平台,一般都支持这种编程范式,但应该理解,开发的目的是使用信息技术手段解决现实世界的需求和问题,而非死板的为了践行某种规范。

JS并不是严格经典的OOP语言,更偏向于函数式语言,但它支持OOP编程,可能是设计者不想把问题搞得过于复杂,应该没有实现完整的OOP特性。

▢ 0x35: Class, 类

在OOP中,类是用来抽象和描述一种类型的对象,所使用的数据和程序结构。使用类可以抽象的描述和封装属性和方法。

基于类作为模板,可以创建具体的对象,这样过程称为实例化。这个对象可以继承类的属性结构和方法,并体现其具体和个性化。

▢ 0x36: Constructior , 构造方法

基于某个类,创建实例时,定义并被调用的特殊方法。构造方法可以给开发者一个时机,在实例化时进行一些初始化数据或者额外的处理操作。

构造方法还可以限制构造实例时所使用的参数,增强代码安全性。

▢ 0x37: Getter/Setter, 读取/设置方法

在类的实例中,用于读取和设置属性值的特殊方法。

js中,使用get和set关键字来对某个以属性名作为名称的方法进行修饰。然后在引用或者设置属性的值的时候,系统会自动调用这个方法。

这些方法在对象类定义中是可选的。笔者理解,它们可以提供一个机制,可以让开发者在设置和读取属性值时,有机会可以做一些额外的操作,并且将这些操作封装到对象内部,让使用无需关心内部实现细节。

▢ 0x38: Instance Method, 实例方法

必须要基于类,创建实例后,才能使用的方法。实例方法通常和实例本身的属性和行为相关。

▢ 0x39: Static Method, 静态方法

对于类,可以不用实例化,就可以直接引用和使用的方法。这个方法和实例、属性等没有关系。通常在工具类使用静态方法,可以简化代码编写。

在实例中也可以以调用实例方法的方式,调用实例类的静态方法。但显然这就跟这个实例特性没有直接关系了。

▢ 0x3A: Array, 数组

在js中,数值或者对象的有序有限集合。通常数组元素可以基于其在数组中的位置(索引)来访问或者设置。作为动态类型语言,JS的数组非常灵活,其成员可以是不同的数据类型,包括null。js提供了一整套相关的函数,来高效处理数组相关的操作,包括创建、插入、移除、拆分、合并、查找、遍历、规约等等,非常方便和强大。

在所有的编程语言中,基本都有数组的概念,处理的模式和逻辑也类似,所以数组是计算机编程而非JS独有的基础概念和技术。

▢ 0x3B: Map, 图

图是使用键-值对方式,进行组织的数据和对象集合。集合成员的访问方式通常通过"键(key)"的方式。和数组不同,这个key不是简单的位置索引,而是对象。

▢ 0x3C: Set, 集

集是元素的简单集合。集没有顺序,而且其成员不会重复(值和对象引用)。

▢ 0x3D: Garbage Collection, 垃圾回收

广义上的GC是一种自动内存管理的机制。在GC之前,程序运行过程中的内存管理,特别是使用过的变量和对象的内存占用释放,是由开发者编程手动进行管理的。这在复杂庞大的应用中,会带来很多的工作量和错误风险,所以很多编程系统和运行时都引入了GC来自动化管理内存。

GC会简化开发过程,但通常也会带来性能问题,一般体现在GC操作时,会占用一些CPU和内存资源,影响当前程序的正常运行。编写良好的GC程序,会使这个过程透明高效,并将对性能的影响降到最低。这通常也是衡量一个运行时设计是否优秀的一个重要指标(图为某js程序运行中,GC作用对内存的影响)。

▢ 0x3E: Weak Map/Weak Set, 弱映射/弱集合

WeakMap是ES6新增的一种特殊映射表数据结构。WeakMap的使用方式和Map一样,但有几点区别。WM的键只能是对象(不能使用其他类型如字符串);WM不能枚举,也没有清空方法,如keys、values、entries方法都不可用;此处的Weak(弱)是弱引用的意思,就是使用完成后,集合元素会被垃圾回收机制优先处理。而普通的Map元素,只要Map存在,即使已经使用完成,元素本身却无法被垃圾回收。

所以,WM特别适合于临时性的存储大型对象和数据,而不用太担心内存无法及时释放和泄露的问题。

▢ 0x3F: Synchronous, 同步

同步是一种执行模式,指程序中,多个函数的执行,严格按照编写的顺序执行。在调用过程中,前面的函数或者方法执行完毕,后面的方法才能启动。也就是说,后面的方法执行,完全取决于前序方法的执行结果和状态,这又称为"Block,阻塞"。

▢ 0x40: Asynchronous, 异步

异步也是一种执行模式,指代码在执行中,在一个执行序列中,虽然某个函数的执行启动有先后之分,但是否启动执行和前面函数是否完成没有关系。

这个对于来自过程编程和对象编程的开发者而言,刚开始不太好理解。因为在编写程序时,永远都有代码的编写和调用的先后顺序。但这个顺序是一种"表示"的顺序,并非程序执行和启动的逻辑顺序。

这里,同步和异步都是针对函数而言的,就是函数本身是同步或者异步执行的模式,并且运行在其父函数的同步或异步模式的环境中。由于名义上后续函数的执行,不受前面函数的执行和状态的影响,异步执行又被称为"Non-Block,非阻塞"。

▢ 0x41: Non-Blocking Event Loop, 非阻塞事件循环

这里有三个关键字:非阻塞、事件、循环。

这里就涉及到js程序执行的核心机制了。js程序启动后,会建立一个主线程,它会执行程序入口开始的代码和函数,这时在正常情况下是同步操作;如果遇到异步函数,这个方法不会被立刻执行,而是将会被添加到一个Task Queue中;一旦主进程的同步代码执行完毕,或者主线程进入空闲,它就会使用一个无限循环的小程序(称为Event Loop,事件循环),每次循环产生的事件都会触发一个动作行为,就是检查任务队列;如果不为空,则将从队列中取出第一个任务,并推入执行栈中运行。这样,基于这个事件循环,就实现了同步代码与异步代码的交织执行。异步代码不会堵塞同步代码,保证主线程响应性,同时可以利用主线程空闲时间片段执行待办任务,减少无效等待时间,提高资源利用率。

显然,非阻塞事件循环的处理模式,特别适合于Web应用这种请求/响应式的,处理过程多样且随机化程度比较高的应用场景。事实上,这个模式是现在所有主流的Web应用平台都使用的方式(原生或者改进后的)。

非阻塞事件循环的潜在缺点是,如果若异步任务过多,或者处理耗时太长,主线程仍可能会被挤占导致响应迟缓。所以需要适度控制异步任务。

笔者想到的非阻塞事件循环,最形象,但不那么贴切的例子,就是"回转寿司"了。

▢ 0x42: Single Threaded, 单线程/

js的执行引擎在运行js代码的时候,使用非阻塞事件循环的模式,为了简单高效,只使用单线程进行工作。由于任务执行本身是异步非阻塞的,所以这个单线程只负责任务的调度和结果处理,本身不需要在多个线程(可能还包括程序上下文,甚至操作系统态)之间进行频繁切换,在现代高速CPU系统上运行非常快速高效。至于异步执行的程序,当然本身也是在相同的操作系统和硬件平台上运行,但减少了切换干扰,更好的达到了多线程并发执行的效果。

▢ 0x43: Cluster, 群集/

考虑到现代的硬件平台,都是多CPU、多核或者超线程架构。为了适应这种趋势,更加充分的利用硬件特性,nodejs引入了cluster(群集)执行模式。

Node.js中的cluster模块可以实现简单的多进程模型,可以有效的在新硬件平台上提高应用程序的并发性能。cluster运行在程序启动时,由主进程(master)生成多个工作进行(worker),每个工作进行都运行独立的nodejs程序实例(相同的代码),主进程和工作进程可以使用进程间通信(IPC)机制交换消息。对于Web应用,cluster有相关的机制,让工作进程可以分担网络请求和负载。

使用cluster,nodejs程序可以充分利用计算资源,提高单一系统的并发处理能力。合理的规划和设计,使应用程序可以在worker失效时也可以提供服务,并在失效时还可以实现恢复,提升系统的健壮性。

但IPC的性能相对应用内部通信有一定损失,被认为不适合于做业务级的数据传输和交换。管理多个工作进程,也会带来系统的复杂性和额外的资源消耗。但总体而言瑕不掩瑜,cluster很好的规避和改善了js程序单线程的缺陷,应该很好的加以应用。


本章节到此结束,后续内容更精彩!!

相关推荐
2401_857622661 小时前
SpringBoot框架下校园资料库的构建与优化
spring boot·后端·php
正小安1 小时前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序
2402_857589361 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
哎呦没2 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch3 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光3 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   3 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发
长路 ㅤ   3 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web3 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常3 小时前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式