JS数据类型

本文详细介绍了JavaScript中的九种数据类型,包括Number、String、Boolean、undefined、null、Symbol、Function,以及如何声明和使用函数,包括参数、返回值、变量作用域等概念,并强调了函数的单一职责和良好的命名规范。
摘要由CSDN通过智能技术生成

Javascript的九种数据类型


Number

let n = 123 ; n = 123.456
number 类型代表整数和浮点数。
数字可以有很多操作,比如,乘法 *、除法 /、加法 +、减法 - 等等。
除了常规的数字,还包括所谓的“特殊数值(“special numeric values”)”也属于这种类型:Infinity、-Infinity 和 NaN。

String

JavaScript 中的字符串必须被括在引号里。
let str =“Hello”;
let str2 =‘Hello’;
let phrase =hello,${str};
反引号是_ _功能扩展 引号。它们允许我们通过将变量和表达式包装在 … 中,来将它们嵌入到字符串中。 < b r / > {…} 中,来将它们嵌入到字符串中。<br /> 中,来将它们嵌入到字符串中。<br/>{…} 内的表达式会被计算,计算结果会成为字符串的一部分。可以在 ${…} 内放置任何东西:诸如名为 name 的变量,或者诸如 1 + 2 的算数表达式,或者其他一些更复杂的。

Boolean

boolean 类型仅包含两个值:true 和 false。
这种类型通常用于存储表示 yes 或 no 的值:true 意味着 “yes,正确”,false 意味着 “no,不正确”。

undefined

undefined 的含义是** 未被赋值_。_**
例如: 一个变量已被声明,但未被赋值 ,那么就是undefined

null

null从逻辑上来讲,表示一个**空对象指针,**这也就是typeof传一个object的原因
undefined值就是由null派生而来,接着看:
console.log(null == undefined) //true
即使相同:**但用途却不一样,**null是一个假值,在定义将来要保存对象值的变量时,建议使用null来初始化,不要适用任何其他值。

Symbol

建议读这位大佬的文章

function

我们经常需要在脚本的许多地方执行很相似的操作。
例如,当访问者登录、注销或者在其他地方时,我们需要显示一条好看的信息。
函数是程序的主要“构建模块”。函数使该段代码可以被调用很多次,而不需要写重复的代码。
我们已经看到了内建函数的示例,如 alert(message)、prompt(message, default) 和 confirm(question)。但我们也可以创建自己的函数。

函数声明

使用 函数声明 创建函数。

看起来就像这样:

function showMessage() { alert( 'Hello everyone!' ); }

function 关键字首先出现,然后是 函数名,然后是括号之间的 参数 列表(用逗号分隔,在上述示例中为空,我们将在接下来的示例中看到),最后是花括号之间的代码(即“函数体”)。

function name(parameter1, parameter2, ... parameterN) { ...body... }

我们的新函数可以通过名称调用:showMessage()。

例如:

function showMessage() { alert( 'Hello everyone!' ); } showMessage(); showMessage();

调用 showMessage() 执行函数的代码。这里我们会看到显示两次消息。

这个例子清楚地演示了函数的主要目的之一:避免代码重复。

如果我们需要更改消息或其显示方式,只需在一个地方修改代码:输出它的函数。

局部变量

在函数中声明的变量只在该函数内部可见。
例如:
function showMessage() { let message = "Hello, I'm JavaScript!"; // 局部变量 alert( message ); } showMessage(); // Hello, I'm JavaScript! alert( message ); // <-- 错误!变量是函数的局部变量

外部变量

函数也可以访问外部变量,例如:
let userName = 'John'; function showMessage() { let message = 'Hello, ' + userName; alert(message); } showMessage(); // Hello, John
函数对外部变量拥有全部的访问权限。函数也可以修改外部变量。
例如:
let userName = 'John'; function showMessage() { userName = "Bob"; // (1) 改变外部变量 let message = 'Hello, ' + userName; alert(message); } alert( userName ); // John 在函数调用之前 showMessage(); alert( userName ); // Bob,值被函数修改了
只有在没有局部变量的情况下才会使用外部变量。
如果在函数内部声明了同名变量,那么函数会 遮蔽 外部变量。例如,在下面的代码中,函数使用局部的 userName,而外部变量被忽略:
let userName = 'John'; function showMessage() { let userName = "Bob"; // 声明一个局部变量 let message = 'Hello, ' + userName; // Bob alert(message); } // 函数会创建并使用它自己的 userName showMessage(); alert( userName ); // John,未被更改,函数没有访问外部变量。
全局变量
任何函数之外声明的变量,例如上述代码中的外部变量 userName,都被称为 全局 变量。
全局变量在任意函数中都是可见的(除非被局部变量遮蔽)。
减少全局变量的使用是一种很好的做法。现代的代码有很少甚至没有全局变量。大多数变量存在于它们的函数中。但是有时候,全局变量能够用于存储项目级别的数据。

参数

我们可以通过参数将任意数据传递给函数。
在如下示例中,函数有两个参数:from 和 text。
function showMessage(from, text) { // 参数:from 和 text alert(from + ': ' + text); } showMessage('Ann', 'Hello!'); // Ann: Hello! (*) showMessage('Ann', "What's up?"); // Ann: What's up? (**)
当函数在 (*) 和 (**) 行中被调用时,给定值被复制到了局部变量 from 和 text。然后函数使用它们进行计算。
这里还有一个例子:我们有一个变量 from,并将它传递给函数。请注意:函数会修改 from,但在函数外部看不到更改,因为函数修改的是复制的变量值副本:
function showMessage(from, text) { from = '*' + from + '*'; // 让 "from" 看起来更优雅 alert( from + ': ' + text ); } let from = "Ann"; showMessage(from, "Hello"); // *Ann*: Hello // "from" 值相同,函数修改了一个局部的副本。 alert( from ); // Ann
当一个值被作为函数参数(parameter)传递时,它也被称为 参数(argument)
换一种方式,我们把这些术语搞清楚:

  • 参数(parameter)是函数声明中括号内列出的变量(它是函数声明时的术语)。
  • 参数(argument)是调用函数时传递给函数的值(它是函数调用时的术语)。

我们声明函数时列出它们的参数(parameters),然后调用它们传递参数(arguments)。
在上面的例子中,我们可以说:“函数 showMessage 被声明,并且带有两个参数(parameters),随后它被调用,两个参数(arguments)分别为 from 和 “Hello””。

默认值

如果一个函数被调用,但有参数(argument)未被提供,那么相应的值就会变成 undefined。
例如,之前提到的函数 showMessage(from, text) 可以只使用一个参数(argument)调用:
showMessage("Ann");
那不是错误,这样调用将输出 “Ann: undefined”。因为参数 text 的值未被传递,所以变成了 undefined。
我们可以使用 = 为函数声明中的参数指定所谓的“默认”(如果对应参数的值未被传递则使用)值:
function showMessage(from, text = "no text given") { alert( from + ": " + text ); } showMessage("Ann"); // Ann: no text given
现在如果 text 参数未被传递,它将会得到值 “no text given”。
这里 “no text given” 是一个字符串,但它可以是更复杂的表达式,并且只会在缺少参数时才会被计算和分配。所以,这也是可能的:
function showMessage(from, text = anotherFunction()) { // anotherFunction() 仅在没有给定 text 时执行 // 其运行结果将成为 text 的值 }
默认参数的计算
在 JavaScript 中,每次函数在没带个别参数的情况下被调用,默认参数会被计算出来。
在上面的例子中,如果传递了参数 text,那么 anotherFunction() 就不会被调用。
如果没传递参数 text,那么 anotherFunction() 就会被调用。
在 JavaScript 老代码中的默认参数
几年前,JavaScript 不支持默认参数的语法。所以人们使用其他方式来设置默认参数。
如今,我们会在旧代码中看到它们。
例如,显式地检查 undefined:
function showMessage(from, text) { if (text === undefined) { text = 'no text given'; } alert( from + ": " + text ); }
……或者使用 || 运算符:
function showMessage(from, text) { // 如果 text 的值为假值,则分配默认值 // 这样赋值 text == "" 与 text 无值相同 text = text || 'no text given'; ... }

后备的默认参数

有些时候,将参数默认值的设置放在函数执行(相较更后期)而不是函数声明时,也行得通。
我们可以通过将参数与 undefined 进行比较,来检查该参数是否在函数执行期间被传递进来:
function showMessage(text) { // ... if (text === undefined) { // 如果参数未被传递进来 text = 'empty message'; } alert(text); } showMessage(); // empty message
……或者我们可以使用 || 运算符:
function showMessage(text) { // 如果 text 为 undefined 或者为假值,那么将其赋值为 'empty' text = text || 'empty'; ... }
现代 JavaScript 引擎支持 空值合并运算符 ??,它在大多数假值(例如 0)应该被视为“正常值”时更具优势:
function showCount(count) { // 如果 count 为 undefined 或 null,则提示 "unknown" alert(count ?? "unknown"); } showCount(0); // 0 showCount(null); // unknown showCount(); // unknown

返回值

函数可以将一个值返回到调用代码中作为结果。
最简单的例子是将两个值相加的函数:
function sum(a, b) { return a + b; } let result = sum(1, 2); alert( result ); // 3
指令 return 可以在函数的任意位置。当执行到达时,函数停止,并将值返回给调用代码(分配给上述代码中的 result)。
在一个函数中可能会出现很多次 return。例如:
function checkAge(age) { if (age >= 18) { return true; } else { return confirm('Got a permission from the parents?'); } } let age = prompt('How old are you?', 18); if ( checkAge(age) ) { alert( 'Access granted' ); } else { alert( 'Access denied' ); }
只使用 return 但没有返回值也是可行的。但这会导致函数立即退出。
例如:
function showMovie(age) { if ( !checkAge(age) ) { return; } alert( "Showing you the movie" ); // (*) // ... }
在上述代码中,如果 checkAge(age) 返回 false,那么 showMovie 将不会运行到 alert。
空值的 return 或没有 return 的函数返回值为 undefined
如果函数无返回值,它就会像返回 undefined 一样:
function doNothing() { /* 没有代码 */ } alert( doNothing() === undefined ); // true
空值的 return 和 return undefined 等效:
function doNothing() { return; } alert( doNothing() === undefined ); // true
不要在 return 与返回值之间添加新行
对于 return 的长表达式,可能你会很想将其放在单独一行,如下所示:
return (some + long + expression + or + whatever * f(a) + f(b))
但这不行,因为 JavaScript 默认会在 return 之后加上分号。上面这段代码和下面这段代码运行流程相同:
return; (some + long + expression + or + whatever * f(a) + f(b))
因此,实际上它的返回值变成了空值。
如果我们想要将返回的表达式写成跨多行的形式,那么应该在 return 的同一行开始写此表达式。或者至少按照如下的方式放上左括号:
return ( some + long + expression + or + whatever * f(a) + f(b) )
然后它就能像我们预想的那样正常运行了。

函数命名

函数就是行为(action)。所以它们的名字通常是动词。它应该简短且尽可能准确地描述函数的作用。这样读代码的人就能清楚地知道这个函数的功能。
一种普遍的做法是用动词前缀来开始一个函数,这个前缀模糊地描述了这个行为。团队内部必须就前缀的含义达成一致。
例如,以 “show” 开头的函数通常会显示某些内容。
函数以 XX 开始……

  • “get…” —— 返回一个值,
  • “calc…” —— 计算某些内容,
  • “create…” —— 创建某些内容,
  • “check…” —— 检查某些内容并返回 boolean 值,等。

这类名字的示例:
showMessage(…) // 显示信息 getAge(…) // 返回 age(gets it somehow) calcSum(…) // 计算求和并返回结果 createForm(…) // 创建表单(通常会返回它) checkPermission(…) // 检查权限并返回 true/false
有了前缀,只需瞥一眼函数名,就可以了解它的功能是什么,返回什么样的值。
一个函数 —— 一个行为
一个函数应该只包含函数名所指定的功能,而不是做更多与函数名无关的功能。
两个独立的行为通常需要两个函数,即使它们通常被一起调用(在这种情况下,我们可以创建第三个函数来调用这两个函数)。
有几个违反这一规则的例子:

  • getAge —— 如果它通过 alert 将 age 显示出来,那就有问题了(只应该是获取)。
  • createForm —— 如果它包含修改文档的操作,例如向文档添加一个表单,那就有问题了(只应该创建表单并返回)。
  • checkPermission —— 如果它显示 access granted/denied 消息,那就有问题了(只应执行检查并返回结果)。

这些例子假设函数名前缀具有通用的含义。你和你的团队可以自定义这些函数名前缀的含义,但是通常都没有太大的不同。无论怎样,你都应该对函数名前缀的含义、带特定前缀的函数可以做什么以及不可以做什么有深刻的了解。所有相同前缀的函数都应该遵守相同的规则。并且,团队成员应该形成共识。

函数 == 注释

函数应该简短且只有一个功能。如果这个函数功能复杂,那么把该函数拆分成几个小的函数是值得的。有时候遵循这个规则并不是那么容易,但这绝对是件好事。
一个单独的函数不仅更容易测试和调试 —— 它的存在本身就是一个很好的注释!
例如,比较如下两个函数 showPrimes(n)。它们的功能都是输出到 n 的 素数。
第一个变体使用了一个标签:
function showPrimes(n) { nextPrime: for (let i = 2; i < n; i++) { for (let j = 2; j < i; j++) { if (i % j == 0) continue nextPrime; } alert( i ); // 一个素数 } }
第二个变体使用附加函数 isPrime(n) 来检验素数:
function showPrimes(n) { for (let i = 2; i < n; i++) { if (!isPrime(i)) continue; alert(i); // 一个素数 } } function isPrime(n) { for (let i = 2; i < n; i++) { if ( n % i == 0) return false; } return true; }
第二个变体更容易理解,不是吗?我们通过函数名(isPrime)就可以看出函数的行为,而不需要通过代码。人们通常把这样的代码称为 自描述
因此,即使我们不打算重用它们,也可以创建函数。函数可以让代码结构更清晰,可读性更强。

Array

添加元素

在数组末尾插入元素

arr[arr.length] = 10
push: arr.push(10) ; arr.push(11,12)

在数组开头插入元素

使用unshift

const arr = [1,2,3];arr.unshift(-1);console.log(arr)//[-1,1,2,3]

splice

arr.splice(5,0,2,3,4) //从索引5开始 删除0个元素,分别添加2,3,4

删除元素

在数组末尾删除元素

arr.pop()

在数组开头删除元素

arr.shift()

在任意位置添加或删除元素

arr.splice(5,3) // 这行代码删除了arr索引5开始的第三个元素
arr.delete(1) 不建议,因为删除的这个位置 将会变成undefined,仍然会占位置

数组合并

const arr = [1];const arr1 = [2]; arr.concact(arr1) // [1,2]

迭代器函数

  1. every
  2. some

返回的是boolean

  1. forEach

与for循环相同,但效率没有for循环高

  1. map和filter

map将会返回每一项的boolean,用来判断一个数是否为偶数这类再方便不过
filter则是将结果为true的组合成新的数组返回

  1. reduce

用来累加求和非常方便
arr.reduce((previous,current)=>previous+current)

普通数组汇编

push() 在数组的末尾位置添加元素
pop() 在数组的最后一个位置删除元素
unshift() 在数组的第一个位置添加元素
shift() 在数组的第一个位置删除元素
sort() 以ASSIC码排序数组元素
reverse() 倒序数组
slice(start,end) 截取数组,不包括结束下标的元素
splice() 删除数组中指定位置的元素
join() 分割数组并转变成字符串
find() 找数组的元素,找到返回true,否则undefined
findIndex() 找到返回下标,找不到返回-1
indexOf() 查找元素,找到返回下标,否则返回-1
includes() 查找元素,返回true或者false
map() 参数为回调函数,遍历返回新数组
forEach() 遍历数组
filter() 过滤方法
every() 全部满足返回true
some() 存在满足返回true
lastIndexOf() 查找方法
reduce() 参数为回调函数,四个参数(前一个,当前,下标,数组)
reduceRight() 参数为回调函数
concat() 合并数组

Es6新增数组方法

点击访问

Object

let o = new Object()
这种语法类型Java,如果没有参数,那么括号可以省略
let o = new Object 但不推荐
每个object实例都有如下属性和方法:

  • constructor 创建当前对象的函数
  • hasOwnProperty 用于判断当前对象实例上是否存在给定的属性
  • isPrototypeof 用于判断当前对象是否为另一个对象的原型
  • propertyIsEnumerable_ 用于判断给定的属性是否可以使用_
  • toLocaleString() 返回对象的字符串表示,该字符串反映对象所在的本地化执行环境
  • toString() 返回对象的字符串表示
  • valueOf() 返回对象对应的字符串、数值或布尔值表示

typeof操作符[不属于]

对 typeof x 的调用会以字符串的形式返回数据类型
最后三行可能需要额外的说明:

  1. Math 是一个提供数学运算的内建 object。
  2. typeof null 的结果为 “object”。这是官方承认的 typeof 的错误,这个问题来自于 JavaScript 语言的早期阶段,并为了兼容性而保留了下来。null 绝对不是一个 object。null 有自己的类型,它是一个特殊值。typeof 的行为在这里是错误的。
  3. typeof alert 的结果是 “function”,因为 alert 在 JavaScript 语言中是一个函数。我们会在下一章学习函数,那时我们会了解到,在 JavaScript 语言中没有一个特别的 “function” 类型。函数隶属于 object 类型。但是 typeof 会对函数区分对待,并返回 “function”。这也是来自于 JavaScript 语言早期的问题。从技术上讲,这种行为是不正确的,但在实际编程中却非常方便。

Biglint[不属于,内置对象]

在 JavaScript 中,“number” 类型无法安全地表示大于 (253-1)(即 9007199254740991),或小于 -(253-1) 的整数。
更准确的说,“number” 类型可以存储更大的整数(最多 1.7976931348623157 * 10308),但超出安全整数范围 ±(253-1) 会出现精度问题,因为并非所有数字都适合固定的 64 位存储。因此,可能存储的是“近似值”。
例如,这两个数字(正好超出了安全整数范围)是相同的:
console.log(9007199254740991+1);// 9007199254740992
console.log(9007199254740991+2);// 9007199254740992

总结

JavaScript 中有八种基本的数据类型(译注:前七种为基本数据类型,也称为原始数据类型,而 object 为复杂数据类型)。

  • 七种原始数据类型:
    • number 用于任何类型的数字:整数或浮点数,在 ±(253-1) 范围内的整数。
    • bigint 用于任意长度的整数。
    • string 用于字符串:一个字符串可以包含 0 个或多个字符,所以没有单独的单字符类型。
    • boolean 用于 true 和 false。
    • null 用于未知的值 —— 只有一个 null 值的独立类型。
    • undefined 用于未定义的值 —— 只有一个 undefined 值的独立类型。
    • symbol 用于唯一的标识符。
  • 以及一种非原始数据类型:
    • object 用于更复杂的数据结构。

我们可以通过 typeof 运算符查看存储在变量中的数据类型。

  • 通常用作 typeof x,但 typeof(x) 也可行。
  • 以字符串的形式返回类型名称,例如 “string”。
  • typeof null 会返回 “object” —— 这是 JavaScript 编程语言的一个错误,实际上它并不是一个 object。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值