整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

JavaScript中的数据类型,看这一篇就够了

JavaScript中的数据类型,看这一篇就够了

据类型

ECMAScript中有5中简单的数据类型(也成为基本数据类型):Undefined、Null、Boolean、Number、String。还有一种复杂的数据类型——Object

注:Object本质上是有一组无序的键值对组成的

1 typeof操作符

鉴于ECMAScript是松散类型的,因此需要一个手段来检测给定的变量时什么类型,typeof就是负责这个功能的操作符。对一个值使用typeof操作符可能返回下列某个字符串:

  • "undefined"——如果这个值未定义
  • "boolean"——如果这个值是布尔值
  • "string"——如果这个值是字符串
  • "number"——如果这个值是数值
  • "object"——如果这个值是对象或null
  • "function"——如果这个值是函数

下面举一些使用typeof操作符的例子:

var message="some string";
alert(typeof message);		// "string"
alert(typeof (message));	// "string"
alert(typeof 95);			// "number"

2 Undefined类型

Undefined类型只有一个值,级特殊的undefined。在使用var声明变量,但未对其加以初始化时,这个变量就是undefined,例如:

var message;
alert(message==undefined);	// true

也可以将变量直接初始化为undefined:

var message=undefined;
alert(message==undefined);	// true

3 Null类型

Null类型是第二个只有一个值得数据类型,这个特殊的值是null。从逻辑角度来看,null值表示一个空**对象**指针,这也正是为什么用typeof检测null值会返回object的原因:

var car=null;
alert(typeof car);	//object

实际上undefined值是派生自null值得,如下例:

alert(null==undefined);	//true

但是两者还是有区别的,如果一个变量暂时不赋值,将来要使用。我们不会把一个变量显示的定义为undefined,而是会定义为null。

4 Boolean类型

Boolean类型是ECMAScript中使用得最多的一种类型,该类型有两个字面值:true和false。

var found=true;
var lost=false;

虽然Boolean类型的字面值只有两个,但ECMAScript中所有类型的值都有与这两个Boolean值等价的值。也就是说能够定义的所有值要么能转成true,要么能转成false,可以用转型函数Boolean()转化。

var message="Hello world";
var messageAsBoolean=Boolean(message);
alert(messageAsBoolean);	//true

下表给出了各种数据类型及其对应的转换规则:

注:n/a(或N/A),是not applicable的缩写,意思是“不适用”。


在流程控制语句中,会自动执行Boolean转换,如下所示:

var message="Hello world!";
if (message) { 			//这里执行了Boolean转换,将message转为true
	alert("Value is true");
}

5 Number类型

Number类型应该是ECMAScript中最令人关注的数据类型了,直接上例子:

var intNum=55;		// 十进制的55
var octalNum=070;		// 八进制的56
var hexNum=0xA;		// 十六进制的10

1.浮点数值

所谓浮点数值,就是该数值中必须包含一个小数点,并且小数点后面必须至少有以为数字,浮点数值的例子:

var floatNum1=1.1;
var floatNum2=0.1;
var floatNum3=.1; 	//有效,但不推荐

由于浮点数值占用的内存是整数值的两倍,所以ECMAScript会不失时机地将浮点数值转换为整数值,如下所示:

var floatNum1=1.;		//小数后面没有数字——解析为1
var floatNum2=10.0;	//整数——解析为10

还有一种可以表示极大或极小的浮点数值的方法——e表示法,如下所示:

var floatNum=3.125e7;	

其含义是3.125*10^7

var floatNum=3e-7;

其含义是3*10^(-7)

2.数值范围

由于内存的限制,ECMAScript并不能保存世界上所有的数值。ECMAScript能够表示的最小数值保存在Number.MIN_VALUE中,这个数值是5e-324;能够表示的最大数值保存在Number.MAX_VALUE中,这个数值是1.7976931348623157e+308。如果某次计算的结果超过这个范围,则会被转换成特殊的Infinity值。

var result=Number.MAX_VALUE + Number.MAX_VALUE;
alert(isFinite(result));    //false

3.NaN

NaN,即非数值(Not a Number),这个数值用于表示一个本来要返回数值的操作数未返回数值的情况,当计算错误的时候,不会抛出错误,而是返回一个NaN,这样就不会影响后面代码的执行。

  • 任何涉及NaN的操作(例如NaN/10)都会返回NaN
  • NaN与任何值都不相等,包括NaN本身
alert(NaN==NaN);	//false
alert(isNaN(NaN));	//true

4.数值转换

有3个函数可以把非数值转换为数值:Number()、parseInt()、parseFloat()

  • Number()——可以用于任何数值类型
  • parseInt()——用于字符串转数值
  • parseFloat()——用于字符串转数值

Number()函数的转换规则如下:

  • 如果是Boolean值,true和false将分别被转换为1和0
  • 如果是数字值,只是简单的传入和返回
  • 如果是null值,返回0
  • 如果是undefined,返回NaN
  • 如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回值
  • 如果是字符串,遵循以下规则:
    • 如果字符串中包含数字,则将其转换为十进制数值
    • 如果字符串中包含有效的浮点格式,如"1.1",则将其转换为对应的浮点数值
    • 如果字符串中包含有效的十六进制格式,如"0xf",则将其转换为相同大小的十进制整数值
    • 如果字符串是空的,则将其转换为0
    • 如果字符串中包含除上述格式之外的字符,则将其转换为NaN

例如:

var num1=Number("Hello world!");	//NaN
var num2=Number("");				//0
var num3=Number("000011");		//11
var num4=Number(true);			//1

由于Number()在转换字符串时比较复杂而且不够合理,因此更常用的是parseInt()函数。parseInt()会从字符串第一个非空格字符开始扫描,如果第一个字符不是数字符号或者负号,parseInt()就会返回NaN。如果第一个字符是数字字符,parseInt()会继续解析第二个字符,知道遇到一个非数字字符。例如,"1234blue"会被转换为1234。"22.5"会被解析成22。

var num1=parseInt("1234blue");  // 1234
var num2=parseInt("");          // NaN
var num3=parseInt("0xA");       // 10(十六进制数)
var num4=parseInt(22.5);        // 22
var num5=parseInt("070");       // 56(八进制数)
var num6=parseInt("70");        // 70(十进制数)
var num7=parseInt("0xf");       // 15(十六进制数)
var num8=parseInt("f",16);      // 15(十六进制数,另一种写法,推荐这么写)

parseFloat()与parseInt()类似,但有两点区别:

  • parseFloat()解析字符串中的第一个小数点是有效的,而第二个小数点无效
  • parseFloat()始终会忽略前导的零
  • 十六进制的字符串始终会被转换成0
  • 如果字符串可以解析为整数,那么parseFloat()会返回整数
 var num1=parseFloat("1234blue");    // 1234(整数)
 var num2=parseFloat("0xA");         // 0
 var num3=parseFloat("22.5");        // 22.5
 var num4=parseFloat("22.34.5");     // 22.34
 var num5=parseFloat("0908.5");      // 908.5
 var num6=parseFloat("3.125e7");     // 31250000

6 String类型

String类型用于表示有零或多个16位Unicode字符组成的字符序列,即字符串。字符串可以用双引号(")或单引号(')表示,因此下面的写法都是有效的:

var firstName="Kobe";
var lastName='Bryant';

1.字符字面量

String数据类型包含一些特殊的字符字面量,也叫转义序列,用于表示非打印字符,或者具有其他用途的字符。这些字符字面量如下表所示:

2.字符串的特点

ECMAScript中的字符串是**不可变**的,也就是说,字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符,首先要销毁原来的字符串,然后在用另一个包含新值得字符串填充该变量,例如:

var lang="Java";
lang=lang + "Script";

第二行的动作是,创建一个能容纳10个字符的新字符串,然后在这个字符串中填充"Java"和"Script",然后将原来的字符串"Java"和字符串"Script"销毁。

3.转换为字符串

要把一个值转换为一个字符串有两种方式。

a. toString()方法,该方法返回字符串的一个副本

var age=11;
var ageAsString=age.toString();		// 字符串"11"
var found=true;
var foundAsString=found.toString();	// 字符串"true"

由于null和undefined值没有toString()方法,可以用下面的String()方法转换为字符串

b.String()方法,可以将任何类型的值转换为字符串。

  • 如果值有toString()方法,则电泳该方法并返回相应的结果
  • 如果值是null,则返回"null"
  • 如果值是undefined,则返回"undefined"

下面看几个例子:

var value1=10;
var value2=true;
var value3=null;
var value4;
    
alert(String(value1));  // "10"
alert(String(value2));  // "true"
alert(String(value3));  // "null"
alert(String(value4));  // "undefined"

7 Object类型

ECMAScript中的对象其实就是一组数据和功能的集合。Object对象创建的方法如下:

var o=new Object();

Object的每个实例具有如下属性和方法:

  • constructor:保存着用于创建当前对象的函数。对于前面的例子而言,构造函数就是Object()
  • hasOwnProperty(propertyName):用于检查给定的属性在当前对象中是否存在
  • isPrototypeOf(object):用于检查传入的对象是否是当前对象的原型
  • propertyIsEnumerablepropertyName():用于检查给定的属性能否能用for-in语句来枚举
  • toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应
  • toString():返回对象的字符串表示
  • valueOf():返回对象的字符串、数值或布尔值表示。通常与toString()方法的返回值相同


如果这篇博客对你有用,点个赞再走呗~

S中有8种数据类型,分别是:

  1. String(字符串)
  2. Number(数字)
  3. Boolean(布尔值)
  4. Undefined(未定义)
  5. Null(空)
  6. Object(对象)
  7. Symbol(符号)
  8. bigint(在ES2020版本中,定义的一种数据类型),专门用来表示大整数

数值(Number):

- 数值就是现实生活中的数字,包括整数(int)和浮点数(float)

- 在js中,所有的数字都是number类型

- 数值在计算机底层使用64位的二进制数据保存

- 所以在JS中,并不是可以精确的表示任意数字

- 对于整数来说,精确表示最大值 九千万亿,9后边15个零

- 特殊的数字:

Infinity 表示正无穷

-Infinity 表示负无穷

NaN (Not a Number) 表示非法数字

了解:

- 为了解决JS中不能存储大整数的问题,在ES2020版本中,

定义了一种新的数据的数据类型(bigint),专门用来表示大整数

- 大整数以n结尾,大小没有限制,但是目前标准还没有正式推出,

即使推出也不会立即被所有浏览器支持(主要是IE),所以现在只需了解一下即可。

var a=10; // 整数

a=3.5; // 浮点数

// 创建数字时,默认创建的都是10进制的数字,可以通过一些特殊方式,来通过其他的进制来创建数字

// 0b 开头表示二进制数字

// 0o 开头表示八进制数字

// 0x 开头表示十六进制数字

a=0b10; // 使用二进制的形式创建数字

a=0o10; // 使用八进制的形式创建数字

a=0xff; // 使用十六进制的形式创建数字

//在JS中可以确保大部分整数运算得到一个精确的结果,但是一旦超过16位数字,运算结果是不精确的值

a=9111111111111432; // 16位整数可以精确表示

a=91111111111114325; // 超过16位,数字显示为近似值

a=911111111111143259111111111111432591; // 当超过一定范围,数字将会以科学计数法来显示

a=911111111111143259111111111111432591 ** 10; // 当数字再大的时候,会显示Infinity,表示正无穷

//在JS中,小数可以确保小数点后15位的值准确,超过15位则会显示近似值

a=1.123456789012345;

//在JS中,小数的计算可能会出现近似的结果

//如果计算要求的精度比较高,千万不要在JS中直接算

a=0.1 + 0.2;

a=10 - 'hello';

// console.log(a);

Var b=911111111111143251239111111111111432512391111111111114325123n;

// console.log(b);


字符串 (String):

- 在JS中使用字符串来表示语音、文字这些内容

- 字符串需要使用引号引起来

- 单引号双引号都可以,但是注意不要混合使用

- 同类型的引号是不能嵌套的

- 在JS中,使用 \ 作为转义字符

例子:

\" --> "

\' --> '

\ --> \

\t --> 制表符(缩进)

\n --> 在console换行

- 引号只在当前行起作用

var a='Hello';

a="Hello";

// a="hello'; //不要这么写

// a='Hello Hello "aaaa"';

a="Hello H\nello \"aa\\aa\"";

// console.log(a);

a="hello hello How are you";


布尔值(boolean):

布尔值(boolean),主要用来进行逻辑判断

- 布尔值只有两个值:

true 表示真

false 表示假

var a=false;

console.log(typeof a) // boolean

- typeof的情况:

typeof 检查 数字时,返回 number

typeof 检查 字符串时,返回 string

typeof 检查 布尔值时, 返回 Boolean


null和undefined:

空值(null)

- 空值就表示没有,表示空的对象

- 空值只有一个 null

未定义(undefined)

- 当我们声明了一个变量,又不给变量赋值时,它的值就是undefined

- 一般我们不会主动为一个变量赋值为undefined

typeof的返回值:

检查 null时,它会返回 object (这个是JS中的bug,一个历史悠久的bug)

检查 undefined时,它会返回 undefined

var a=null;

a=undefined; // 通常情况下不会这么写

console.log(typeof null);

console.log(typeof undefined);

基本数据类型5种:

在JS中的这几种数据类型,被统称为基本数据类型:

数值(number)

字符串(string)

布尔值(boolean)

空值(null)

未定义(undefined)

- 基本数据类型是构建程序的基石,所有的数据都是以上几种数据组合而成。

- 所有的基本数据类型,都是不可变的。

- 在JS中,变量并不真正的存储值

- 在JS中,变量就相当于值的别名

Symbol

Symbol是一种原始类型,可以使用 Symbol() 来创建一个新的 Symbol 对象。Symbol 通常用于作为对象属性的键(key),因为添加到对象中的 Symbol 属性不会出现在 for…in 循环、Object.keys()、Object.getOwnPropertyNames() 等方法中。这使得 Symbol 成为一种适合用于定义隐藏的属性的机制。

需要注意的是,虽然 Symbol 是基本数据类型之一,但是在逻辑运算中,Symbol 类型的值不能被强制转换为其他数据类型。

检查类型tyepof:

var a=10;

var b='10';

//typeof 用来检查一个值的类型

// 注意:typeof检查的是值的类型,而不是变量的类型(变量也没有类型)

//用法:tyepof 值


console.log(typeof a); //number

console.log(typeof NaN); //number

console.log(typeof '10'); // string

console.log(typeof false); // boolean

console.log(typeof undefined); //undefined

console.log(typeof null); // 'object' 是js底层遗留问题


console.log(typeof Array) // 'function'

console.log(typeof Function) // 'function'

console.log(typeof Objcet) // 'function'

console.log(typeof {}); // 'object'

console.log(typeof []); // 'object'


欢迎关注我的原创文章:小伙伴们!我是一名热衷于前端开发的作者,致力于分享我的知识和经验,帮助其他学习前端的小伙伴们。在我的文章中,你将会找到大量关于前端开发的精彩内容。

学习前端技术是现代互联网时代中非常重要的一项技能。无论你是想成为一名专业的前端工程师,还是仅仅对前端开发感兴趣,我的文章将能为你提供宝贵的指导和知识。

在我的文章中,你将会学到如何使用HTML、CSS和JavaScript创建精美的网页。我将深入讲解每个语言的基础知识,并提供一些实用技巧和最佳实践。无论你是初学者还是有一定经验的开发者,我的文章都能够满足你的学习需求。

此外,我还会分享一些关于前端开发的最新动态和行业趋势。互联网技术在不断发展,新的框架和工具层出不穷。通过我的文章,你将会了解到最新的前端技术趋势,并了解如何应对这些变化。

我深知学习前端不易,因此我将尽力以简洁明了的方式解释复杂的概念,并提供一些易于理解的实例和案例。我希望我的文章能够帮助你更快地理解前端开发,并提升你的技能。

如果你想了解更多关于前端开发的内容,不妨关注我的原创文章。我会不定期更新,为你带来最新的前端技术和知识。感谢你的关注和支持,我们一起探讨交流技术共同进步,期待与你一同探索前端开发的奇妙世界!

#web网站#

于 JS 初学者,理解链表可能是一项比较困难的任务,因为 JS 没有提供内置的链表。在像 JS 这样的高级语言中,我们需要从头开始实现此数据结构,如果你不熟悉此数据结构的工作方式,则实现部分会变得更加困难 ?。

在本文中,我们将讨论如何将链表存储在数据库中,实现链表的添加和删除,查找以及反转链表等操作。在实现链表之前,需要知道相比数组和对象,链表的优点是什么。

我们知道,数组中的元素以索引编号和顺序存储在数据库中:

在使用数组时,在开始或特定索引处添加/删除元素这样的操作可能是一项性能较低的任务,因为我们必须移动所有其他元素的索引,造成这种原因是由数组的编号索引特性导致的。

使用对象可以解决上述问题。由于在对象中,元素存储位置是随机的,因此,在执行诸如在开始处或特定索引处添加/删除元素之类的操作时,无需移动元素的索引:

尽管在对象中添加和删除元素速度很快,但是从上图可以看出,在进行迭代操作时,对象并不是最佳选择,因为对象的元素存储在随机位置。因此,迭代操作可能需要很长时间。这是链表引出的原因。

那么什么是链表呢 ?

从名字本身可以看出它是一个以某种方式链表。那么它是如何链接的,列表包含什么呢?

链表由具有两个属性的节点组成:数据和指针

节点内的指针指向列表中的下一个节点。链表中的第一个节点称为head。为了更好地理解,让我们看一下描述链表图示:

从上图可以看出,每个节点都有两个属性,datapointer。指针指向列表中的下一个节点,最后一个节点的指针指向null,上图是一个单链表 ?。

链表和对象时有很大的不同。在链表中,每个节点都通过指针(pointer)连接到下一个节点。因此,我们在链表的每个节点之间都有连接,而在对象中,键值对是随机存储的,彼此之间没有连接。

本文由小智翻译,欢迎关注《大迁世界

接着,我们实现一个存储整数的链表。由于 JS 不提供内置的链表支持,因此我们将使用对象和类来实现链表 ?

class Node {
  constructor (value) {
    this.value = value
    this.next = null
  }
}

class LinkedList {
  constructor () {
    this.head = null
    this.tail = this.head
    this.length = 0
  }
  append (value) {
  }

  prepend (value) {

  }

  insert (value, index) {

  }

  lookup (index) {

  }

  remove (index) {

  }

  reverse () {
    
  }
}

在上面的代码中,我们创建了两个类,一个用于来链表本身,一个是节点本身。如我们所讨论的,每个节点将具有两个属性,一个和一个指针(对应 next 字段)。

LinkedList类包含三个属性,head(初始值为null),用于存储链表的最后一个节点的tail(也指向null)和用于保存链表长度的length属性。接着,我们来实现里面的方法 ?。

append (按顺序添加值)

这个函数将一个节点添加到链表的末尾。为了实现这个函数,我们需要理解它需要执行的一些操作:

从上图中,我们可以通过以下方式实现append函数:

  append (value) {
    const newNode = new Node(value)
    if (!this.head) {
      this.head = newNode
      this.tail = newNode
    } else {
      this.tail.next = newNode
      this.tail = newNode
    }
    this.length++
  }

简单的对 append 方法解释一下 ?:

const linkedList1 = new LinkedList()
linkedList1.append(2)

检查head是否指向null,此时的head指向null,因此我们创建一个新对象,并将新对象分配给headtail:

let node = new Node(2)
this.head = newNode
this.tail = newNode

现在,headtail 都指向同一个对象,这一点很重要,要记住。

接着,我们再向链表添加两个值:

linkedList1.append(3)
linkedList1.append(4)

现在,head 不指向null,所以我们进入append函数的else分支:

this.tail.next = node

由于headtail 都指向同一个对象,tail的变化都会导致head对象的变化,这是JS 中对象的工作方式。在JavaScript中,对象是通过引用传递的,因此 headtail都指向存储对象的相同地址空间。上面这行代码相当于

this.head.next = node;

下一行:

this.tail = node

现在,在执行完上面的代码行之后,this.head.nextthis.tail指向同一对象,因此,每当我们添加新节点时,head对象都会自动更新。

执行三次append之后,linkedList1 的结构应该是这样的:

head: {value: 2 , next: {value: 3, next: {value: 4,next: null}}}
tail : {value: 4, next: null}
length:3

从上面的代码中我们可以看到,链表的append函数的复杂度是O(1),因为我们既不需要移动索引,也不需要遍历链表。

我们来看下一个函数 ?

prepend (将值添加到链表的开头)

为了实现此函数,我们使用Node类创建一个新节点,并将该新节点的下一个对象指向链表的head 。接下来,我们将新节点分配给链表的head

与append函数一样,这个函数的复杂度也是O(1)。

  prepend (value) {
  const node = new Node(value)

  node.next = this.head
  this.head = node
  this.length++
}

就像append函数一样,此函数的复杂度也为O(1)

insert (在特定索引处添加值)

在实现此函数之前,我们先看看它的一个转化过程。因此,出于理解目的,我们先创建一个值很少的链表,然后可视化insert函数。insert 函数接受两个参数,值和索引:

let linkedList2 = new LinkedList()
linkedList2.append(23)
linkedList2.append(89)
linkedList2.append(12)
linkedList2.append(3)
linkedList2.insert(45,2)

第1步:

遍历链表,直到到达index-1位置:

第2步:

将索引为1的节点的指针(在本例中为89)分配给新节点(在本例中为45):

第3步:

将新节点(45)的 next 指向给下一个节点(12)

这就是执行插入操作的方式。通过以上可视化,我们观察到需要在index-1位置和index位置找到节点,以便可以在它们之间插入新节点。在代码中实现:

insert (value, index) {
  if (index >= this.length) {
  this.append(value)
}

  const node = new Node(value)

  const { prevNode, nextNode } = thisg.getPrevNextNodes(index)
  prevNode.next = node
  node.next = nextNode

  this.length++
}

简单分析一下上面的函数:

如果index的值大于或等于length属性,则将操作移交给append函数。对于 else 分支,我们使用 Node 类创建一个新节点,接下来观察一个新函数getPrevNextNodes(),通过该函数我们可以接收prevNodenextNode的值。getPrevNextNodes函数的实现如下:

 getPrevNextNodes(index){
    let count = 0;
    let prevNode = this.head;
    let nextNode = prevNode.next;

    while(count < index - 1){
      prevNode = prevNode.next;
      nextNode = prevNode.next;
      count++;
    }

    return {
      prevNode,
      nextNode
    }
  }

通过遍历链表返回在index-1位置和index位置的节点,并将prevNodenext属性指向新节点,并将新节点的next属性指向nextNode

链表的插入操作的复杂度为 O(n),因为我们必须遍历链表并在index-1index 位置搜索节点。尽管复杂度为O(n),但我们发现此插入操作比对数组的插入操作快得多,在数组中,我们必须将所有元素的索引移到特定索引之后,但是在链接中,我们仅操纵 index-1index 位置的节点的下一个属性。

remove (删除特定索引处的元素)

实现了插入操作之后,删除操作就比较容易理解,因为它几乎与插入操作相同,当我们从getPrevNextNodes函数获取prevNodenextNode值时,我们必须在remove中执行以下操作:

remove(index){
  let {previousNode,currentNode} = this.getNodes(index)
  previousNode.next = currentNode.next
  this.length--
}

删除操作的复杂度也为 O(n),类似于插入操作,链表中的删除操作比数组中的删除操作要快。

reverse (反转链表)

虽然看起来很简单,但反转链表常常是实现起来最令人困惑的操作,因此,在面试中会经常询问这个操作。在实现这个函数之前,让我们先把反转链表的策略可视化一下。

为了反转链表,我们需要跟踪三个节点,previousNodecurrentNodenextNode

考虑下面的链表:

let linkedList2 = new LinkedList()
linkedList2.append(67)
linkedList2.append(32)
linkedList2.append(44)

第一步:

开始,previousNode的值为null,而currentNode的值为head

第二步:

接下来,我们将nextNode分配给currentNode.next

第三步:

接下来,我们将currentNode.next属性指向previousNode

第三步:

现在,我们将previousNode移至currentNode,将currentNode移至nextNode

这个过程从步骤2重复操作,一直到currentNode 等于 null

reverse (){
  let previousNode = null
  let currentNode = this.head

  while(currentNode !== null) {
    let nextNode = currentNode.next
    currentNode.next = previousNode
    previousNode = currentNode
    currentNode = nextNode
  }

  this.head = previousNode
}

就像我们看到的一样,直到currentNode===null,我们一直在遍历和移动这些值。最后,我们将previousNode值分配给head

反向运算的复杂度为O(n)

查找 (查找特定索引的值)

这个操作很简单,我们只是遍历链表并返回特定索引处的节点。这个操作的复杂度也是O(n)

lookup(index){
    let counter = 0;
    let currentNode = this.head;
    while(counter < index){
      currentNode = currentNode.next;
      counter++;
    }
    return currentNode;
  }

好了,我们已经完成了用javascript实现单个链表的基本操作。单链表和双链表的区别在于,双链表的节点具有指向前一个节点和下一个节点的指针。

总结

链表为我们提供了快速的append(末尾添加元素)和prepend(开头添加元素)操作。尽管链表中的插入操作的复杂度为O(n),但比数组的插入操作要快得多。使用数组时我们面临的另一个问题是大小复杂性,当使用动态数组时,在添加元素时,我们必须将整个数组复制到另一个地址空间,然后添加元素,而在链表中,我们不需要 面对这样的问题。

在使用对象时,我们面临的问题是元素在内存中的随机位置,而在链表中,节点是通过指针相互连接的,指针提供了一定的顺序。

我是小智,我们下期见!


作者:Vivek Bisht 译者:前端小智 来源:soshace

原文:https://blog.soshace.com/understanding-data-structures-in-javascript-linked-lists/