javascript中的内置对象和数据结构
bigegpt 2024-10-19 02:51 8 浏览
简介
基本上所有的程序员都使用过javascript,我们在web中使用javascript,我们在服务器端使用nodejs,js给大家的第一映像就是简单,但是可能并不是所有人都系统的了解过js中的内置对象和数据结构。
今天,一起来看看吧。
基础类型
js是一种弱类型的动态语言,虽然是弱类型的,但是js本身定义了很多种数据类型。
js中有7种基础类型:分别是undefined,Boolean,Number,String,BigInt,Symbol和null。
undefined
undefined会自动赋值给刚刚声明的变量。举个例子:
var x; //create a variable but assign it no value
console.log("x's value is", x) //logs "x's value is undefined"
Boolean和Boolean对象
Boolean的值就是true 或者 false。
除了基础类型的Boolean值外,还有一个Boolean对象,用来封装boolean值。
如果是用new Boolean来构造Boolean对象的话,下面的例子中Boolean的初始值都是false:
var bNoParam = new Boolean();
var bZero = new Boolean(0);
var bNull = new Boolean(null);
var bEmptyString = new Boolean('');
var bfalse = new Boolean(false);
下面boolean对象的初始值都是true:
var btrue = new Boolean(true);
var btrueString = new Boolean('true');
var bfalseString = new Boolean('false');
var bSuLin = new Boolean('Su Lin');
var bArrayProto = new Boolean([]);
var bObjProto = new Boolean({});
注意,我们不要使用Boolean对象来进行if条件的判断,任何Boolean对象,即使是初始值是false的Boolean对象,if条件判断,都是true:
var x = new Boolean(false);
if (x) {
// this code is executed
}
var x = false;
if (x) {
// this code is not executed
}
如果非要使用if条件判断,我们可以使用Boolean函数或者!!如下所示:
var x = Boolean(expression); // use this...
var x = !!(expression); // ...or this
var x = new Boolean(expression); // don't use this!
Number和BigInt
Number和BigInt是JS中的两个数字类型,其中Number表示的双精度64位二进制格式,其范围是-(253 ? 1) and 253 ? 1.
除此之外,Number还有三个值:+Infinity, -Infinity, 和 NaN。
前面两个表示的是正负最大值。NaN表示的是 Not-A-Number。
我们可以通过isNaN来判断是否是一个Number:
function sanitise(x) {
if (isNaN(x)) {
return NaN;
}
return x;
}
console.log(sanitise('1'));
// expected output: "1"
console.log(sanitise('NotANumber'));
// expected output: NaN
BigInt表示任意精度的整数,使用BigInt可以进行超出Number精度整数的运算。
我们可以通过在整数后面加上n来表示BigInt。
> const x = 2n ** 53n;
9007199254740992n
> const y = x + 1n;
9007199254740993n
注意,和Boolean一样,Number和BitInt也有wrapper对象类型。
看下Number的wrapper:
Number('123') // returns the number 123
Number('123') === 123 // true
Number("unicorn") // NaN
Number(undefined) // NaN
看下BitInt的wrapper类型:
const theBiggestInt = 9007199254740991n
const alsoHuge = BigInt(9007199254740991)
// ? 9007199254740991n
const hugeString = BigInt("9007199254740991")
// ? 9007199254740991n
const hugeHex = BigInt("0x1fffffffffffff")
// ? 9007199254740991n
const hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111")
// ? 9007199254740991n
String
js中的String是不可变的,同样的String基础类型也有和它对应的String wrapper对象。
String基础类型和不使用new的String函数是一致的:
const string1 = "A string primitive";
const string2 = String('A string primitive');
上面两个String是一致的。但是如果使用new来构造String对象,那么两者是不一样的:
let s_prim = 'foo'
let s_obj = new String(s_prim)
console.log(typeof s_prim) // Logs "string"
console.log(typeof s_obj) // Logs "object"
let s1 = '2 + 2' // creates a string primitive
let s2 = new String('2 + 2') // creates a String object
console.log(eval(s1)) // returns the number 4
console.log(eval(s2)) // returns the string "2 + 2"
我们可以通过String对象的valueOf()方法,获得其String基础类型。
Symbol
Symbol是一个唯一的不可变的基础类型,一般用在对象的key中。
// Here are two symbols with the same description:
let Sym1 = Symbol("Sym")
let Sym2 = Symbol("Sym")
console.log(Sym1 === Sym2) // returns "false"
Symbol是不支持new操作的:
let sym = new Symbol() // TypeError
如果你真的想创建Symbol对象,则可以使用Object():
let sym = Symbol('foo')
typeof sym // "symbol"
let symObj = Object(sym)
typeof symObj // "object"
null
null表示引用的是无效的Object对象或者地址。
虽然null可以看做是primitive,但是null其实是一个Object,所有的对象都来自null:
typeof null === 'object' // true
Object
Object是js中的一种数据类型,几乎所有的对象都继承自Object,它存储的是key-value形式的数据,我们可以通过使用Ojbect()方法或者new Object()或者Object字面量的方式来创建Object。
let o = {}
let o = {a: 'foo', b: 42, c: {}}
let a = 'foo', b = 42, c = {}
let o = {a: a, b: b, c: c}
注意使用Object()或者new Object()是一样的效果,都会得到一个Object对象。
在ES2015之后,我们还可以使用动态的对象属性:
let param = 'size'
let config = {
[param]: 12,
['mobile' + param.charAt(0).toUpperCase() + param.slice(1)]: 4
}
console.log(config) // {size: 12, mobileSize: 4}
Function
Function也是一个Object,JS中的所有函数都是Function对象。
(function(){}).constructor === Function
那么通过Function构造函数和function函数定义创建出来的函数有什么区别呢?
使用new Function创建的函数,其作用域范围是global,我们看一下具体的例子:
var x = 10;
function createFunction1() {
var x = 20;
return new Function('return x;'); // this |x| refers global |x|
}
function createFunction2() {
var x = 20;
function f() {
return x; // this |x| refers local |x| above
}
return f;
}
var f1 = createFunction1();
console.log(f1()); // 10
var f2 = createFunction2();
console.log(f2()); // 20
Date
Date是js中用来操作时间的Object。我们看下Date的常用例子:
let today = new Date()
let birthday = new Date('December 17, 1995 03:24:00')
let birthday = new Date('1995-12-17T03:24:00')
let birthday = new Date(1995, 11, 17) // the month is 0-indexed
let birthday = new Date(1995, 11, 17, 3, 24, 0)
let birthday = new Date(628021800000) // passing epoch timestamp
let [month, date, year] = ( new Date() ).toLocaleDateString().split("/")
let [hour, minute, second] = ( new Date() ).toLocaleTimeString().slice(0,7).split(":")
Array
JS内置了很多种不同类型的Array,最常用的就是Array字面量和Array Object。
我们看下怎么创建一个Array:
let fruits = ['Apple', 'Banana'];
console.log(fruits.length); // 2
console.log(fruits[0]); // "Apple"
let fruits = new Array('Apple', 'Banana');
console.log(fruits.length); // 2
console.log(fruits[0]); // "Apple"
遍历Array:
let fruits = ['Apple', 'Banana']
fruits.forEach(function(item, index, array) {
console.log(item, index)
})
// Apple 0
// Banana 1
添加Item到Array:
let newLength = fruits.push('Orange')
// ["Apple", "Banana", "Orange"]
从最后删除item:
let last = fruits.pop() // remove Orange (from the end)
// ["Apple", "Banana"]
从前面删除item:
let first = fruits.shift() // remove Apple from the front
// ["Banana"]
从前面添加item:
let newLength = fruits.unshift('Strawberry') // add to the front
// ["Strawberry", "Banana"]
删除某个index的item:
let removedItem = fruits.splice(pos, 1) // this is how to remove an item
// ["Strawberry", "Mango"]
删除多个item:
let vegetables = ['Cabbage', 'Turnip', 'Radish', 'Carrot']
console.log(vegetables)
// ["Cabbage", "Turnip", "Radish", "Carrot"]
let pos = 1
let n = 2
let removedItems = vegetables.splice(pos, n)
// this is how to remove items, n defines the number of items to be removed,
// starting at the index position specified by pos and progressing toward the end of array.
console.log(vegetables)
// ["Cabbage", "Carrot"] (the original array is changed)
console.log(removedItems)
// ["Turnip", "Radish"]
拷贝array:
let shallowCopy = fruits.slice() // this is how to make a copy
// ["Strawberry", "Mango"]
除了Array之外,JS还内置了特定类型的Array:
- Int8Array
- Uint8Array
- Uint8ClampedArray
- Int16Array
- Uint16Array
- Int32Array
- Uint32Array
- Float32Array
- Float64Array
- BigInt64Array
- BigUint64Array
这些特定类型的Array中只能存储特定类型的值。
Keyed collections
除了数组之外,JS中还有key-value的集合,比如:Map,Set,WeakMap和WeakSet。
对Map来说,我们可以通过使用set,get,has,delete等犯法来对Map进行操作:
let contacts = new Map()
contacts.set('Jessie', {phone: "213-555-1234", address: "123 N 1st Ave"})
contacts.has('Jessie') // true
contacts.get('Hilary') // undefined
contacts.set('Hilary', {phone: "617-555-4321", address: "321 S 2nd St"})
contacts.get('Jessie') // {phone: "213-555-1234", address: "123 N 1st Ave"}
contacts.delete('Raymond') // false
contacts.delete('Jessie') // true
console.log(contacts.size) // 1
遍历Map:
let myMap = new Map()
myMap.set(0, 'zero')
myMap.set(1, 'one')
for (let [key, value] of myMap) {
console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one
for (let key of myMap.keys()) {
console.log(key)
}
// 0
// 1
for (let value of myMap.values()) {
console.log(value)
}
// zero
// one
for (let [key, value] of myMap.entries()) {
console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one
使用forEach来遍历map:
myMap.forEach(function(value, key) {
console.log(key + ' = ' + value)
})
// 0 = zero
// 1 = one
Set中存储的是唯一的对象。
我们看下Set的操作:
let mySet = new Set()
mySet.add(1) // Set [ 1 ]
mySet.add(5) // Set [ 1, 5 ]
mySet.has(1) // true
mySet.delete(1) // removes 1 from the set
set的遍历:
// logs the items in the order: 1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}
for (let item of mySet) console.log(item)
WeakMap,WeakSet和Map于Set的区别在于,WeakMap的key只能是Object对象,不能是基本类型。
为什么会有WeakMap呢?
对于JS中的Map来说,通常需要维护两个数组,第一个数组中存储key,第二个数组中存储value。每次添加和删除item的时候,都需要同时操作两个数组。
这种实现有两个缺点,第一个缺点是每次查找的时候都需要遍历key的数组,然后找到对应的index,再通过index来从第二个数组中查找value。
第二个缺点就是key和value是强绑定的,即使key不再被使用了,也不会被垃圾回收。
所以引入了WeakMap的概念,在WeakMap中,key和value没有这样的强绑定关系,key如果不再被使用的话,可以被垃圾回收器回收。
因为引用关系是weak的,所以weakMap不支持key的遍历,如果你想遍历key的话,请使用Map。
本文作者:flydean程序那些事
本文链接:http://www.flydean.com/js-built-in-objects-structures/
本文来源:flydean的博客
欢迎关注我的公众号:「程序那些事」最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
相关推荐
- 得物可观测平台架构升级:基于GreptimeDB的全新监控体系实践
-
一、摘要在前端可观测分析场景中,需要实时观测并处理多地、多环境的运行情况,以保障Web应用和移动端的可用性与性能。传统方案往往依赖代理Agent→消息队列→流计算引擎→OLAP存储...
- warm-flow新春版:网关直连和流程图重构
-
本期主要解决了网关直连和流程图重构,可以自此之后可支持各种复杂的网关混合、多网关直连使用。-新增Ruoyi-Vue-Plus优秀开源集成案例更新日志[feat]导入、导出和保存等新增json格式支持...
- 扣子空间体验报告
-
在数字化时代,智能工具的应用正不断拓展到我们工作和生活的各个角落。从任务规划到项目执行,再到任务管理,作者深入探讨了这款工具在不同场景下的表现和潜力。通过具体的应用实例,文章展示了扣子空间如何帮助用户...
- spider-flow:开源的可视化方式定义爬虫方案
-
spider-flow简介spider-flow是一个爬虫平台,以可视化推拽方式定义爬取流程,无需代码即可实现一个爬虫服务。spider-flow特性支持css选择器、正则提取支持JSON/XML格式...
- solon-flow 你好世界!
-
solon-flow是一个基础级的流处理引擎(可用于业务规则、决策处理、计算编排、流程审批等......)。提供有“开放式”驱动定制支持,像jdbc有mysql或pgsql等驱动,可...
- 新一代开源爬虫平台:SpiderFlow
-
SpiderFlow:新一代爬虫平台,以图形化方式定义爬虫流程,不写代码即可完成爬虫。-精选真开源,释放新价值。概览Spider-Flow是一个开源的、面向所有用户的Web端爬虫构建平台,它使用Ja...
- 通过 SQL 训练机器学习模型的引擎
-
关注薪资待遇的同学应该知道,机器学习相关的岗位工资普遍偏高啊。同时随着各种通用机器学习框架的出现,机器学习的门槛也在逐渐降低,训练一个简单的机器学习模型变得不那么难。但是不得不承认对于一些数据相关的工...
- 鼠须管输入法rime for Mac
-
鼠须管输入法forMac是一款十分新颖的跨平台输入法软件,全名是中州韵输入法引擎,鼠须管输入法mac版不仅仅是一个输入法,而是一个输入法算法框架。Rime的基础架构十分精良,一套算法支持了拼音、...
- Go语言 1.20 版本正式发布:新版详细介绍
-
Go1.20简介最新的Go版本1.20在Go1.19发布六个月后发布。它的大部分更改都在工具链、运行时和库的实现中。一如既往,该版本保持了Go1的兼容性承诺。我们期望几乎所...
- iOS 10平台SpriteKit新特性之Tile Maps(上)
-
简介苹果公司在WWDC2016大会上向人们展示了一大批新的好东西。其中之一就是SpriteKitTileEditor。这款工具易于上手,而且看起来速度特别快。在本教程中,你将了解关于TileE...
- 程序员简历例句—范例Java、Python、C++模板
-
个人简介通用简介:有良好的代码风格,通过添加注释提高代码可读性,注重代码质量,研读过XXX,XXX等多个开源项目源码从而学习增强代码的健壮性与扩展性。具备良好的代码编程习惯及文档编写能力,参与多个高...
- Telerik UI for iOS Q3 2015正式发布
-
近日,TelerikUIforiOS正式发布了Q32015。新版本新增对XCode7、Swift2.0和iOS9的支持,同时还新增了对数轴、不连续的日期时间轴等;改进TKDataPoin...
- ios使用ijkplayer+nginx进行视频直播
-
上两节,我们讲到使用nginx和ngixn的rtmp模块搭建直播的服务器,接着我们讲解了在Android使用ijkplayer来作为我们的视频直播播放器,整个过程中,需要注意的就是ijlplayer编...
- IOS技术分享|iOS快速生成开发文档(一)
-
前言对于开发人员而言,文档的作用不言而喻。文档不仅可以提高软件开发效率,还能便于以后的软件开发、使用和维护。本文主要讲述Objective-C快速生成开发文档工具appledoc。简介apple...
- macOS下配置VS Code C++开发环境
-
本文介绍在苹果macOS操作系统下,配置VisualStudioCode的C/C++开发环境的过程,本环境使用Clang/LLVM编译器和调试器。一、前置条件本文默认前置条件是,您的开发设备已...
- 一周热门
- 最近发表
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- resize函数 (64)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- mybatis大于等于 (64)
- xcode-select (66)
- httperror403.14-forbidden (63)
- logstashinput (65)
- hadoop端口 (65)
- dockernetworkconnect (63)
- esxi7 (63)
- vue阻止冒泡 (67)
- c#for循环 (63)
- oracle时间戳转换日期 (64)
- jquery跨域 (68)
- php写入文件 (73)
- java大写转小写 (63)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)