JavaScript 语言基础一

111 阅读11分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情

《JavaScript高级程序设计》 第三章语言基础,阅读的一些笔记摘录

语法

区分大小写

JS 中一切都是区分的大小写的,无论是函数名变量操作符等都是区分大小写的。
换句说就是 testTest是两个变量

标识符

所谓标识符就是变量函数属性函数参数名称,标识符可以由一个或者多个下列字符号组成

  • 第一个字符必须是字母 、下划线 或者 $ 符号
  • 剩下的字符可以是 字母、下划线、$ 或者数字
  • 书写方式以驼峰形式书写,即第一个单词的首字母小写,后面的每一个单词的首字母大写
// 合法
var nameFirst = '' // 驼峰形式
var _nameFirst1 = ''
var $nameFirst2 = ''

// 不合法
var 123bane = ''

注释

  • 单行注释
  • 多行注释
// 单行注释

/*
	多行注释
	多行注释
*/

严格模式

  • "use strict" 关键字
  • 一些不规范的写法会被处理
  • 对不安全的语法会抛出错误
  • 也可以单独使用在函数体内

关键字和保留字

  • 关键字和保留字在 JS 中是有特殊用途的,比如:判断语句用到 if,循环语句 for while
abstractelseinstanceofsuper
booleanenumintswitch
breakexportinterfacesynchronized
byteextendsletthis
casefalselongthrow
catchfinalnativethrows
charfinallynewtransient
classfloatnulltrue
constforpackagetry
continuefunctionprivatetypeof
debuggergotoprotectedvar
defaultifpublicvoid
deleteimplementsreturnvolatile
doimportshortwhile
doubleinstaticwith

变量

  • JS 的变量是松散性的
  • 可以保存任何的数据
  • 可以用三个关键字来声明变量,var、let、const

var

用 var 来声明变量,var 是一个关键字,后面跟上变量名称,例如:var message。var 声明有以下特点

  • var 声明范围是函数作用域
  • 在全局作用域下声明变量,变量会成为全局对象 window 的属性
  • var 声明的变量会被提升到函数作用域的顶部
  • var 可以重复定义同一个变量
  • 定义的变量可以重复的赋值
  • 声明的变量未赋值,会默认赋值 undefined
// 当前全局作用域  window
var name = '张三'
console.log(window.name) // '张三'

function fn(){
  console.log(age); // undefined 
  var age = 10
  var age =  11
  age = 12
  age = 15
  console.log(age) // 15
}

fn() 

// 变量提升的转换
function fn(){
  var age;
  console.log(age); 
  age = 10
	age = 11
  age = 12
  age = 15
  console.log(age)
}

let

let 是 ES6 中新增的声明变量关键字,有以下特点

  • let 声明范围是块级作用域
  • 块级作用域是函数作用的子集,所以对 var 声明变量的限制同样也适用于 let
  • 全局作用域下声明变量,变量不会成为全局对象 window 的属性
  • 不能重复声明同一个变量
  • 定义的变量可以重复赋值
  • 声明变量未赋值,会默认赋值 undefined
  • 声明变量不会提升
  • 暂时性死区,变量声明之前是无法使用的,使用会抛出错误,只能在声明变量语句后使用变量

const

const 和 let 一样都是 ES6 中新增的声明变量关键字,有以下特点

  • const 与 let 特点基本相同
  • 唯一区别是,const 声明的变量必须初始化赋值
  • 声明后的变量是不可以再被赋值
  • 声明的限制只适用于变量的引用,对于修改对象的属性是不受限制的

数据类型

  • Undefined
  • Null
  • String
  • Number
  • Boolean
  • Object
  • Symbol

Undefined

Undefined 类型只有一个值,就是特殊值 undefined。

  • 当声明一个变量但未对变量初始化的时候,变量会被默认赋值 undefined
  • typeof 一个未声明的变量也是返回 undefined , 所以建议声明变量的时候初始化变量,这样就能知道检测出 undefined 是一个未声明变量,而不是一个声明了但未初始化的变量。
  • 是一个假值
  • 是由 null 派生出来的值, null == undefined 值是相等的

Null

Null 类型同样只有一个值,即特殊值 null。

  • 表示空对象指针
  • 一个假值
  • 用途与 undefined 不一样,变量要保存对象,但是当时又没有那个对象保存,就会赋值 null
  • typeof null === 'object',检测返回是一个对象。(不同的对象在 JS 底层都表示为二进制,JS 二进制的前三位是表示类型的,object 类型的前三位是000,null 的底层二级制表示都是000,所以会被认为是对象)

Boolean

Boolean类型有两个布尔值 truefalse。布尔值字面量 true 和 false 是区分大小写的,因此 True 和 False(及其他大小混写形式) 是有效的标识符,但不是布尔值。将其他类型的数据转换成布尔值,可以调用 Boolean() 函数。

转换成布尔值

数据类型转换为 true 的值转换为 false 的值
Booleantruefalse
String非空字符串空字符串
Number非零数值(包括无穷)0、NaN
Object任意对象null
Undefined(无,不存在)undefined

Number

Number 类型是使用 IEEE 754 格式的整数和浮动数(双精度型)。通过 64 位表示数字。

Snipaste_2022-12-03_09-14-50.png 图片说明:

  1. 第0位:表示符号,0 表示正,1 表示负 (s)
  2. 第1位到11位:表示存储指数部分 (e)
  3. 第12位到63位:表示存储小数部分 (m)
  • 整数
    • 十进制,基本数值字面量格式
    • 八进制,以0o开头,然后是八进制数 ( 0 ~ 7)
    • 十六进制, 以 0x开头的 (区分大小写),然后是十六进制数字(09 以 及 AF)。十六进制数字中的字母大小写均可。
  • 浮点数
    • 带小数点的数字
    • 存储是整数的两倍,JS 会尽可能的将浮点数转换成整数处理,比如:1.0 会当做 1 处理
    • 科学记数法,3.125e7 相当于 31250000, 0.0000000003 相当于 3e-8
  • 值得范围
    • Number.MIN_VALUE
    • Number.MAX_VALUE
    • Infinity
    • -Infinity
    • isFinite() // 检测是否是无穷值
  • NaN
    • 不是一个数值,表示在返回一个数值的时候失败了
    • NaN 等于任何数 ,包括自己 NaN === NaN // false
    • isNaN, Number.isNaN 检测 NaN,isNaN 有个bug,比如:isNaN('abc') 返回得true,'abc'是一个字符串不是NaN,isNaN只是判断传入得值是不是一个数值,所以要重新改造下;
function isNaNMethod (val){
  return typeof val === 'number' && isNaN(val)
}

转换为数值

  1. Number() 函数,将任何数据类型转换成数值
  • 布尔值,true 转换为1, false 转换为 0
  • 数值直接返回
  • null 返回 0
  • undefined 返回 NaN
  • 字符串
    • 包含数值字符,字符前面带加号、减号,转换为一个十进制数值,忽略前置 0 ,例如:Number('011') =>11
    • 包含有效的浮点数格式,返回相应的浮点数值,忽略前置 0
    • 包含有效的十六进制字符串格式,将十六进制字符串转换为十进制整数值
    • 除以上字符串外,都返回 NaN
  • 对象,会先调用 valueOf 方法,并且按照上述规则转换返回值,如果值是 NaN,则再会调用 toString() 方法,并按照上述规则转换返回值
  1. parseInt() 函数,将字符串转换成整数
  • 忽略前置空格,从第一个非空字符串开始转换
  • 第一个字符不是数值、加号或减号,则返回 NaN
  • 空字符串返回 NaN
  • 第一个字符是数值、加号或减号,则依次检测每一个字符,一直到字符串末尾,或碰到非字符串为止,例如: parseInt('123aaaa') => 123, parseInt('22.4') => 22, 小数点不是有效的整数字符
  • 第一个参数传入的值若不是字符串,会调用 toString() 方法返回字符串
  • 还可以传入第二个参数,指定要转换的进制数 (2 ~ 36)
如果提供了十六进制参数,那么字符串前面的"0x"可以省掉:
let num1 = parseInt("AF", 16); // 175 
let num2 = parseInt("AF"); // NaN

let num1 = parseInt("10", 2); // 2,按二进制解析
let num2 = parseInt("10", 8); // 8,按八进制解析
let num3 = parseInt("10", 10); // 10,按十进制解析
let num4 = parseInt("10", 16); // 16,按十六进制解析
  1. parseFloat() 函数,将字符串转换成浮点数值
  • 转换方式和 parseInt 类似
  • 第一个小数点有效,第二个无效
  • 忽略开头的零
  • 只解析十进制值,所以十六进制的字符串始终返回 0
let num1 = parseFloat("1234blue"); // 1234,按整数解析
let num2 = parseFloat("0xA"); // 0 
let num3 = parseFloat("22.5"); // 22.5 
let num4 = parseFloat("22.34.5"); // 22.34 
let num5 = parseFloat("0908.5"); // 908.5 
let num6 = parseFloat("3.125e7"); // 31250000

String

  • 表示零或多个 16 位 Unicode 字符
  • 可以用一对单引号,一对双引号,一对反引号包围
let name = 'zhangsan'
let name = "zhangsan"
let name = `zhangsan`
  • 字符串字面量
    • \n 换行
    • \t 制表
    • \b 退格
    • \r 回车
    • \f 换页
    • \ 反斜杠
    • ' 单引号
    • " 双引号
    • ` 反引号
  • 字符串模板
    • 一对反引号包围,例如:name
    • 插值,插值中可以是变量,任意的 JS 表达式,所有插入的值都会调用 toString() 强制转换成字符串

转换成字符串

  1. toString()
  • 除 null 和 undefined 外都有 toString() 方法, 其实就是继承了Object的方法
  • 对数值的调用,还可以传入参数,指定返回进制数的字符串
let num = 10; 
console.log(num.toString()); // "10" 
console.log(num.toString(2)); // "1010" 
console.log(num.toString(8)); // "12" 
console.log(num.toString(10)); // "10" 
console.log(num.toString(16)); // "a"
  1. String()
  • 如果值有 toString() 方法,则调用 toString() 方法并且不传入任何值,返回结果
  • 如果值是 null,返回 'null'
  • 如果值是undefined,返回 'undefined'

Object

  • 对象是一组数据和方法的集合
  • 字面量可用通过花括号创建,也可以用 new Object() 创建对象
var obj = {}
var obj = new Object()
  • 属性和方法
    • constructor:创建对象得构造函数
    • hasOwnProperty(propertyName): 判断当前对象上(非原型)是否存在该属性
    • isPrototypeOf(object): 判断当前对象是否是另一个对象得原型
    • propertyEnumerable(propertyName): 判断给定得属性是否可以使用
    • toLocaleString() : 返回对象的字符串表示,字符串反映当前的本地执行环境
    • toString(): 返回对象的字符串表示
    • valueOf(): 返回对象的原始值

Symbol

Symbol 类型是 ES6 新增的符号,是原始值,并且符号的实例是唯一,不可以变得。符号的用途主要就是确保对象属性使用唯一标识符,避免属性冲突。

  • Symbol(): 基础用法
  • Symbol.for(): 全局注册,第一次使用字符调用的时候,会先检查全局注册表中是否存在该符号,不存在就新建一个添加到全局注册表中,若存在则就返回符号实例
  • Symbol.keyFor(): 查询全局注册
  • Symbol.asyncIterator: 一个方法,该方法返回对象默认的 AsyncIterator。由 for-await-of 使用
class Emitter {
  constructor(max){
    this.max = max
    this.asyncIdx = 0
  }

  async *[Symbol.asyncIterator](){
    while(this.asyncIdx < this.max){
      yield new Promise((resolve)=>resolve(this.asyncIdx++))
    }
  }
}

async function asyncCount (){
  let emitter = new Emitter(5)

  for await (const x of emitter ) {
    console.log(x)
  }
}

asyncCount()
// 0
// 1
// 2
// 3
// 4
  • Symbol.hasInstance:一个方法,该方法决定一个构造器对象是否认可一个对象是它的实例, 由 instanceof 使用(instanceof 原理就是检测构造函数的 prototype属性 是否在对象的原型链上出现)
function Foo() {} 
let f = new Foo(); 
console.log(Foo[Symbol.hasInstance](f)); // true 


class Bar {} 
let b = new Bar(); 
console.log(Bar[Symbol.hasInstance](b)); // true

class Bar {} 
class Baz extends Bar { 
 static [Symbol.hasInstance]() { 
 return false; 
 } 
} 
let b = new Baz(); 
// Baz 是由 Bar 继承而来,所以对象 b 的原型链上是由 Bar 的,
console.log(Bar[Symbol.hasInstance](b)); // true 
console.log(b instanceof Bar); // true 
console.log(Baz[Symbol.hasInstance](b)); // false 
console.log(b instanceof Baz); // false
  • Symbol.isConcatSpreadable: 一个布尔值,如果是true,一位置对象应该用 Array.prototype.concat 将数组打平
  • Symbol.iterator: 一个方法,该方法返回对象的迭代器。由 for-of 使用。
class Emitter {
  constructor(max) {
    this.max = max;
    this.idx = 0;
  }

  *[Symbol.iterator](){
    while(this.idx < this.max){
      yield new Promise((resolve)=> resolve(this.idx++))
    }
  }
}

function fnCount(){
	let emitter = new Emitter(5)
  for (const x of emitter){
    console.log(x)
  }
}

fnCount()
// 0
// 1
// 2
// 3
// 4
  • Symbol.match: 一个正则表达式的方法,该方法是用正则表达式去匹配字符。由 String.prototype.match 使用
  • Symbol.search: 一个正则表达式的方法,该方法是返回字符串中匹配正则表达式的索引
  • Symbol.replace: 一个正则表达式方法,该方法是替换一个字符串中匹配的子串
  • Symbol.split: 一个正则表达式的方法,该方法在匹配正则表达式的索引位置拆分字符串
  • Symbol.toPrimitive: 一个方法,该方法是将对象转换成相应的原始值
  • Symbol.toStringTag: 一个字符串,该字符串用于创建对象的默认字符串
  • Symbol.unscopables: 一个对象,该对象所有的以及继承的属性,都会从关联的对象的 with 环境绑定中排除。
let o = { foo: 'bar' }; 
with (o) { 
 console.log(foo); // bar 
} 
// 设置了 true, 就不能在 with 使用属性了
o[Symbol.unscopables] = { 
 foo: true 
}; 
with (o) { 
 console.log(foo); // ReferenceError 
}