JavaScript基础编程笔记

214次阅读
没有评论

共计 9411 个字符,预计需要花费 24 分钟才能阅读完成。

编程环境

Prettier

Prettier 是一个“有主见”的前端代码格式化工具。

在 VSCode 中安装好 Prettier 插件后,可能需要自定义一些配置,可在项目根目录下添加配置文件.prettierrc

{
  "singleQuote": true,
  "arrowParens": "avoid"
}

配置代码片段

在 VSCode 中,「文件」->「首选项」->「配置用户代码片段」->「新建全局代码片段文件 …」,输入自定义文件名,回车。在文件中写入:

{
  "Print to console": {
    "scope": "javascript,typescript",
    "prefix": "cl",
    "body": ["console.log($1);"],
    "description": "Log output to console"
  }
}

另外,需要对 VSCode 做个设置,在设置中搜索 snippet,把「控制活动代码段是否阻止快速建议」前面的√取消掉。

Node.js

到 Node.js 官网:https://nodejs.org/en/ 进行下载安装。

VSCode 默认终端

VSCode 默认是 PowerShell 终端,修改为 CMD 的操作步骤如下:

「终端」->「新建终端],在终端界面,点击 + 右边的「∨」->「选择默认配置文件」->「Command Prompt」,重启 VSCode。

安装 live-server

npm install live-server -g

在静态文件目录下执行:live-server

live-server 运行在 8080 端口下,可以通过 127.0.0.1:8080 进行访问。

VSCode 生成 html 模板

在设置中搜索「Trigger Expansion On Tab」,前面打上√。然后就能用 ! + tab 自动生成 html 模板了。

JavaScript 组成

ECMAScript 是一种语言标准,规定了 JavaScript 基础语法核心知识,而 JavaScript 是网景公司对 ECMAScript 标准的一种实现。

Web APIs:

  • DOM 操作文档,比如对页面元素进行移动、大小、添加制除等操作。
  • BOM 操作浏览器,比如页面弹窗,检测窗口宽度、存储数据到浏览器等等。

JavaScript 权威网站:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript

输入输出

输入语法

prompt("请输入姓名:")

输出语法

// 向 body 输出内容
document.write("输出的内容")
// 页面弹出警告对话框
alert("输出的内容")
// 控制台输出语法,程序员调试使用
console.log("控制台打印")

代码执行顺序

  • 按 HTML 文档流顺序执行 JavaScript 代码
  • alert()和 prompt()会跳过页面染先被执行

变量

变量声明

let age // 变量声明
console.log(age) // 此时 age 的值为 undefined
age = 18 // 变量赋值
console.log(age) // 此时 age 的值为 18
console.log(typeof age) // number 作为运算符(推荐)console.log(typeof age) // number 函数形式

let name, city // 一次性声明多个变量

let sex = 1 // 变量初始化

使用 let 声明的变量具有块作用域,在代码块 {} 中声明的变量无法在代码块的外部访问。

在局部作用域中,未使用 let 或 const 关键字声明的变量,会自动成为 window 对象的属性,也就是全局变量。

数据类型

有 6 种:

  • number 数值(BigInt)
  • string 字符串
  • boolean 布尔值
  • null 空值
  • undifined 未定义
  • symbol 符号
  • object 对象

前 5 个属于基本数据类型,object 属于引用数据类型。基本数据类型的值直接在 栈内存 中存储;而对象是保存到 堆内存 中的,每创建一个新对象,就会在堆内存中开辟出一个新空间,而变量保存的是对象内存地址。

JavaScript 不区分整数和浮点数,统一用 number 表示。

console.log(10.0 === 10) // true
console.log(Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0001) // true 浮点数比较

// NaN(Not a Number)这个特殊 Number 与所有其他值都不相等,包括它自己。// NaN 是粘性的,任何对 NaN 的操作都会返回 NaN
console.log(NaN === NaN) // false
console.log(NaN + 1) // NaN
console.log(isNaN(NaN)) // true 唯一能判断 NaN 的方法

console.log(9007199254740993) // 9007199254740992
// 比 2^53 大的整数,可使用内置 BigInt 类型,表示方法是在整数后加一个 n
var a = 9007199254740993n
var b = BigInt(9007199254740993) // 使用 BigInt() 把 Number 转成 BigInt
var c = BigInt('0x20000000000001')// 把字符串转成 BigInt
console.log(a === b, a === c) // false true

null 和 undefined:

  • null 表示一个“空”值
  • undefined 表示值“未定义”
  • 大多数情况下,都应该用 null
  • undefined 仅在判断函数参数是否传递的情况下有用
console.log(null + 1) // 1

let money
console.log(money + 100) // NaN 对 undefined 进行运算操作,结果是 NaN
console.log(money + '100') // undefined100 用 undefined 连接字符串,将得到一个含 undefined 的字符串

模板字符串:

let age = 18
// 外面用反引号,里面用 ${变量名}
console.log(` 我 ${age}岁了 `) // 我 18 岁了

字符串是不可变的,对字符串某个索引赋值,不会有任何错误,但也没有任何效果:

let s = 'abc'
s[1] = 'd'
console.log(s) // abc

JavaScript 有两种比较运算符:

  • == 会自动转换数据类型再比较
  • === 不会自动转换数据类型,如果数据类型不一致,返回 false,如果一致,再比较

不要使用 == 比较,始终坚持使用 === 比较。

strict 模式

在 strict 模式下运行的 JavaScript 代码,强制申明变量,未申明变量就使用,将导致运行错误。

'use strict'
age = 18 // 报错 age is not define

常量

用 const 关键字声明的变量是只读的。一旦一个变量被赋值为 const,它就不能被重新赋值。

const G = 9.8
console.log(G)

但是,使用 const 分配给变量的对象(包括数组和函数)仍然是可变的。使用 const 声明只能防止变量标识符的重新分配。为了确保数据不被改变,JavaScript 提供了一个函数 Object.freeze。

const MATH_CONSTANTS = {PI: 3.14,}
Object.freeze(MATH_CONSTANTS)

类型转换

隐式转换

规则:

  • + 号两边只要有一个是字符串,都会把另外一个转成字符串
  • 除了 + 以外的算术运算符,比如 – * / 等都会把数据转成数字类型

小技巧:

  • + 号作为正号解析可以转换成数字型
  • 任何数据和字符串相加结果都是字符串
    console.log(+"111") // 转换为数字型

显式转换

转换为 string

null 和 undifined 没有 toString()方法,使用 String()方法会将 null 直接转换为 ”null”,将 undifined 直接转换为 ”undifined”。

转换为 number

Number()

  1. 如果是纯数字的字符串,则直接将其转换为数字
  2. 如果字符串中有非数字的内容,则转换为 NaN
  3. 如果字符串是一个空串或全是空格,则转换为 0
  4. true 转成 1,false 转成 0
  5. null 转成 0
  6. undifined 转成 NaN

parseInt()
将一个字符串中的有效整数内容取出来,然后转换为 number。

parseFloat()
作用和 parseInt()类似,不同的是它可以获得有效的小数。

转换为 boolean

  • 除了 0 和 NaN,其余都是 true
  • 除了空串,其余都是 true
  • null 和 undefined 都会转换为 false
  • 对象转换为 true

运算符

赋值

??= 为空赋值,只有当变量的值为 null 或 undefined 时才会对变量进行赋值:

let a = 100
a ??= 200
console.log(a) //100

a = null
a ??= 200
console.log(a) //200

?. 是链判断运算符,允许开发人员读取深度嵌套在对象链中的属性值,而不必验证每个引用。当引用为空时,表达式停止计算并返回 undefined。

let s1 = {
  name: '张三',
  address: {city: '北京',},
}
let s2 = {
  name: '李四',
  address: null,
}
function test(stu) {console.log(stu.address?.city)
}

test(s1) // 北京
test(s2) //undefined

逻辑中断

短路:只存在于 && 和 || 中,当满足一定条件会让右边代码不执行。

  • &&:左边为 false 就短路
  • ||:左边为 true 就短路

原因:通过左边能得到整个式子的结果,因此没必要再判断右边。

运算结果:无论 && 还是 ||,运算结果都是最后被执行的表达式值,一般用在变量赋值。

console.log(11 && 22) //22
console.log(11 || 22) //11

展开运算符

展开运算符(…)能将一个数组进行展开,典型应用场景:求数组最大值、合并数组等。

const arr = [1, 3, 4]
console.log(Math.max(...arr)) //4

const arr1 = [1, 3, 4]
const arr2 = [2, 8, 9]
const arr = [...arr1, ...arr2]
console.log(arr) //[1, 3, 4, 2, 8, 9]

let obj = {name: '张三', age: 18}
let obj2 = {...obj} // 复制对象
console.log(obj2)

Unicode 编码

在字符串中使用转义字符输入 Unicode 编码,u 四位编码

console.log("u2620")

在网页中使用 Unicode 编码,&# 编码;(编码是 10 进制的)

<h1>&#9760;</h1>

数组

let arr = [1, 2, 3, 4] // 声明数组
console.log(arr[0]) // 1
console.log(arr.length) // 数组长度
arr.length = 6 // 改变数组长度会导致 Array 大小变化
console.log(arr) // [1, 2, 3, 4, <2 empty items>]

console.log(arr.slice(1, 3)) // [2, 3] 切片操作
console.log(arr.slice(1)) // [2, 3, 4, <2 empty items>]

新增

let arr = [1, 2, 3]
arr.push("4")
console.log(arr) //[1, 2, 3, "4"]
arr.unshift(5)
console.log(arr) //[5, 1, 2, 3, "4"]

删除

let arr = [1, 2, 3, 4]
arr.pop()
console.log(arr) //[1, 2, 3]
arr.shift()
console.log(arr) //[2, 3]

let arr2 = [1, 2, 3, 4, 5, 6]
arr2.splice(1, 2) // 只删除,不添加
console.log(arr2) // [1, 4, 5, 6]
arr2.splice(1, 2, '7', '8', '9') // 删除后添加
console.log(arr2) // [1, '7', '8', '9', 6]
arr2.splice(1, 0, 10) // 只添加,不删除
console.log(arr2) // [1, 10, '7', '8', '9', 6]

去重

const arr = [1, 2, 1, 66, 2, 1, 9, 5]
for (let i = 0; i < arr.length; i++) {const index = arr.indexOf(arr[i], i + 1)
  if (index !== -1) {arr.splice(index, 1)
    i--
  }
}
console.log(arr)

const newArr = []
for (let i of arr) {if (newArr.indexOf(i) === -1) {newArr.push(i)
  }
}
console.log(newArr)

排序

let arr = [2, 4, 3, 5, 1]
arr.sort() // 默认升序
console.log(arr) //[1, 2, 3, 4, 5]
arr.sort((a, b) => b - a) // 降序
console.log(arr) //[5, 4, 3, 2, 1]

let arr2 = [
  {
    name: "张三",
    age: 18,
  },
  {
    name: "李四",
    age: 20,
  },
  {
    name: "王五",
    age: 19,
  },
]
arr2.sort((a, b) => b.age - a.age) // 按 age 降序
console.log(arr2)

合并

let arr = [1, 2]
let arr2 = [3, 4]
let arr3 = arr.concat(arr2, 5, 6)
console.log(arr3) // [1, 2, 3, 4, 5, 6]

console.log(arr3.join('-')) // 1-2-3-4-5-6

遍历

let arr = [1, 2, 7, 8]
let r1 = arr.every((item) => item > 5)
console.log(r1) //false

let r2 = arr.some((item) => item > 5)
console.log(r2) //true

let r3 = arr.filter((item) => item > 5)
console.log(r3) //[7, 8]

let r4 = arr.map((item) => "age=" + item)
console.log(r4) //['age=1', 'age=2', 'age=7', 'age=8']

let r5 = arr.reduce((item1, item2) => item1 + item2) // 累加
console.log(r5) //18

arr.forEach((item, index) => {console.log(index, item)
})

注意:在 forEach 里面 return 不会终止迭代。

迭代器

let arr = [1, 2, 7, 8]
for (let i of arr) {console.log(i) //1 2 7 8
}

let arr = [1, 2, 7, 8]
for (let i of arr.entries()) {console.log(i) //entries()是键值对,keys()是键,values()是值}

伪数组转数组

function f() {a = Array.from(arguments)
  console.log(a.map((item) => "age=" + item))
}
f(18, 19, 20) //['age=18', 'age=19', 'age=20']

搜索

let arr = [1, 13, 2, 44]
console.log(arr.indexOf(13)) //1 找不到返回 -1
console.log(arr.includes(13)) //true

console.log(arr.find((item) => item > 10)) //13
console.log(arr.findLast((item) => item > 10)) //44

console.log(arr.findIndex((item) => item > 10)) //1
console.log(arr.findLastIndex((item) => item > 10)) //3

函数

命名建议

常用动词约定 含义
can 判断是否可执行某个动作
has 判断是否含有某个值
is 判断是否为某个值
get 获取某个值
set 设置某个值
load 加载某些数据

作用域

变量有一个坑,特殊情况:如果函数内部,变量没有声明,直接赋值,会当全局变量看,但是强烈不推荐。

function fn() {num = 10}
fn()
console.log(num) //10

原型对象

创建的每一个函数,解析器都会向函数中添加一个属性 prototype,这个属性对应着一个对象,这个对象就是所谓的 原型对象

当函数以构造函数调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,可以通过__proto__来访问该属性。

当访问对象的一个属性或方法时,会先在对象自身中寻找,有则直接使用,没有则会去原型对象中寻找(找到直接使用)。

通过__proto__能访问对象的原型,还可以通过类的 prototype 属性,来访问实例的原型。修改原型时,最好通过类去修改,好处:

  • 一修改就是修改所有实例的原型
  • 无需创建实例即可完成对类的修改

原则上,原型尽量不要手动改。要改也不要通过实例对象去改,而是通过 类.prototype去修改,且最好不要直接给 prototype 去赋值。

原型对象也是对象,它也有原型,即原型的原型。0bject 是所有对象的原型,所以任何对象和 0bject 进行 instanceof 运算都会返回 true。

class Person {}
// 向原型中添加 name 属性
Person.prototype.name = '李小龙'
const p = new Person()
console.log(p.hasOwnProperty('name')) // false
console.log(p.__proto__.hasOwnProperty('name')) // true

使用 in 运算符检查属性时,无论属性在对象自身还是在原型中,都会返回 true。而 对象.hasOwnProperty(属性名)用来检查一个对象自身是否含有某个属性。使用 Object.hasOwn(对象,属性名) 也可以用来检查一个对象自身是否含有某个属性,推荐使用这个方法。

早期 JS 中,直接通过函数来定义类。一个函数如果直接调用xxx(),那么这个函数就是一个普通函数。一个函数如果通过 new 调用new xxx(),那么这个函数就是一个构造函数。

toString()

当打印一个对象时,实际上是输出对象 toString()方法的返回值,可为对象添加一个 toString()自来定义输出。

function Person() {}
Person.prototype.toString = function () {return "我是李小龙"}
var p = new Person()
console.log(p.toString())

call()和 apply()

调用函数除了通过 函数 () 这种形式外,还可以通过其他的方式来调用函数。比如,可以通过调用函数对象的 call()和 apply()两个方法来调用函数函数。

  • call 和 apply 除了可以调用函数,还可以用来指定函数中的 this
  • call 和 apply 的第一个参数,将会成为函数执行时的 this
  • 通过 call 方法调用函数,函数的实参直接在第一个参数对象之后依次传递
  • 通过 apply 方法调用函数,函数的实参需要将实参封装到一个数组中统一传递
function fn(a, b) {alert(`${a} + ${b} = ${a + b}`)
}
const obj = {name: '李小龙'}
fn.call(obj, 1, 2)
fn.apply(obj, [3, 4])

bind()

bind()是函数对象的方法,用来创建一个新函数。

  • bind 可以为新函数绑定 this
  • 也可以为新函数绑定参数
function fn(a, b, c) {console.log(a, b, c, this)
}
const obj = {age: 18}
const newFn = fn.bind(obj, 1, 2, 3)
newFn()

arguments 对象

在调用函数时,浏览器会传递进两个隐含的参数:

  1. 函数的上下文对象 this
  2. 封装实参的对象 arguments
    1. arguments 是个类数组对象(不是数组),可通过索引来操作数据,也可以获取长度
    2. 它里边有个属性叫 callee,这个属性对应一个函数对象,就是当前正在执行的函数对象
function func() {console.log(arguments[0], arguments.length, arguments.callee)
}
func("obj", 1, 2)

对象

在浏览器中,浏览器提供了一个 window 对象,window 对象的属性可以通过 window 对象直接访问,访问函数就可以认为是 window 对象的方法。window 对象代表浏览器窗口,通过该对象可以对浏览器窗口进行各种操作。除此之外,window 对象还负责存储 JS 中的内置对象和浏览器的宿主对象。

注意:使用 let 声明的变量不会存储在 window 对象中,而是存在一个无法访问的秘密小地方。

let a = 'a1'
window.a = 'a2'
console.log(a) // a1

创建对象

在使用变量存储对象时,很容易因为改变变量指向的对象,提高代码的复杂度。所以通常情况下,声明存储对象的变量时会使用 const。const 只是禁止变量被重新赋值,对对象的修改没有任何影响。

// 使用对象字面量创建对象
const obj = {
  name: "李小龙",
  age: 18,
}
console.log(obj) // {name: '李小龙', age: 18}

// 使用 new 关键字创建对象,new 可以省略
const obj = new Object()
const obj2 = Object({name: "李小龙"})

// 使用构造函数创建对象
function Pig(name, age, sex) {
  this.name = name
  this.age = age
  this.sex = sex
}
const Peppa = new Pig("佩奇", 3, "女")
const George = new Pig("乔治", 4, "男")

使用 new 关键字调用的函数,是构造函数(专门用来创建对象的函数)。

修改对象

在使用变量存储对象时,很容易因为改变变量指向的对象,提高代码的复杂度。所以通常情况下,声明存储对象的变量时会使用 const。

遍历对象

let mySymbol = Symbol()
let obj = {
  name: '李小龙',
  age: 18,
  [mySymbol]: '我是特殊属性',
}

for (let k in obj) {console.log(k, '=', obj[k])
}

符号添加的属性不能枚举。

冻结对象

const obj = {
  name: "佩奇",
  age: 10,
  hobby: {one: "唱歌",},
}
Object.freeze(obj) // 浅冻结,使第一层数据不可修改

// 深冻结数据
function deepFreeze(obj) {Object.freeze(obj)
  for (let i in obj) {if (obj.hasOwnProperty(i)) {if (typeof obj[i] === "object") {deepFreeze(obj[i])
      }
    }
  }
}

正文完
 0
阿伯手记
版权声明:本站原创文章,由 阿伯手记 于2023-08-02发表,共计9411字。
转载说明:本站原创内容,除特殊说明外,均基于 CC BY-NC-SA 4.0 协议发布,转载须注明出处与链接。
评论(没有评论)
验证码

阿伯手记

阿伯手记
阿伯手记
喜欢编程,头发渐稀;成长路上,宝藏满地
文章数
766
评论数
204
阅读量
443560
今日一言
-「
热门文章
职场救急!AI请假话术生成器:1秒定制高通过率理由

职场救急!AI请假话术生成器:1秒定制高通过率理由

超级借口 不好开口?借口交给我!智能生成工作请假、上学请假、饭局爽约、约会拒绝、邀约推辞、万能借口等各种借口理...
夸克网盘快传助手提高非VIP下载速度

夸克网盘快传助手提高非VIP下载速度

夸克网盘限速这个大家都知道,不开会员差不多限速在几百 K。那有没有办法在合法合规途径加速下载夸克网盘呢?这里推...
国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

本文收集了目前国内已部署 DeepSeek 模型的第三方列表,个个都是免费不限次数的满血版 DeepSeek,...
巴别英语:用美剧和TED演讲轻松提升英语听力与口语

巴别英语:用美剧和TED演讲轻松提升英语听力与口语

还在为枯燥的英语学习而烦恼吗?巴别英语通过创新的美剧学习模式,让英语学习变得生动有趣。平台提供海量美剧和 TE...
Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 是一款在线中文姓名生成器,可在几秒内生成符合个人需求的中文名字。...
TVAPP:开源电视盒子资源库,一键打造家庭影院

TVAPP:开源电视盒子资源库,一键打造家庭影院

导语 TVAPP 是一个专为 Android TV 电视盒子用户打造的开源影音资源库,集成了影视、直播、游戏等...
2025年12月 每日精选

2025年12月 每日精选

关于每日精选栏目 发现一些不错的资源,点击 这里 快速投稿。 12 月 26 日 .ax 顶级域 目前全球唯一...
最新评论
15220202929 15220202929 怎么用
八对 八对 麻烦大佬更新下【堆新】的友链站名:八对星星描述:极目星视穹苍无界•足履行者大地有疆链接:https://8dui.com图标:https://cf.8dui.com/logo.webp横标:https://cf.8dui.com/logo-w.webp订阅:https://8dui.com/rss.xml
三毛笔记 三毛笔记 已添加
DUINEW DUINEW 已添加贵站,期待贵站友链~博客名称:堆新博客地址:https://duinew.com/博客描述:堆新堆新,引力向新!——堆新(DUINEW)博客头像:https://d.duinew.com/logo.webp横版头像:https://d.duinew.com/logo-w.webp博客订阅:https://duinew.com/rss.xml
hedp hedp 没看懂
bingo bingo 直接生成就可以啦,也可以添加一些选项
满心 满心 申请更新下友联信息,原名:满心记,现名:周天记原域名:qq.mba,现域名:zhoutian.com描述:我在人间混日子
开业吉日 开业吉日 没看明白这个怎么用
开业吉日 开业吉日 beddystories 这个网站太赞了,收藏
热评文章
夸克网盘快传助手提高非VIP下载速度

夸克网盘快传助手提高非VIP下载速度

夸克网盘限速这个大家都知道,不开会员差不多限速在几百 K。那有没有办法在合法合规途径加速下载夸克网盘呢?这里推...
清华大学官方免费DeepSeek教程

清华大学官方免费DeepSeek教程

AI 领域近期最引人注目的焦点当属 DeepSeek,这款由中国创新企业深度求索研发的人工智能工具,正以开放源...
Short-Link 免费开源短网址程序,基于Fastify、Vercel和Supabase构建

Short-Link 免费开源短网址程序,基于Fastify、Vercel和Supabase构建

Short-Link 是一款基于 Fastify、Vercel 和 Supabase 构建的 URL 缩短服务...
国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

本文收集了目前国内已部署 DeepSeek 模型的第三方列表,个个都是免费不限次数的满血版 DeepSeek,...
Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 是一款在线中文姓名生成器,可在几秒内生成符合个人需求的中文名字。...
BeddyStories 完全免费儿童睡前故事库,让孩子随时随地入睡更轻松

BeddyStories 完全免费儿童睡前故事库,让孩子随时随地入睡更轻松

BeddyStories 是一个致力于为儿童提供优质睡前故事的在线平台,用户可以在这里找到来自世界各地的经典故...
DrawLink:一键生成链接视觉卡片,提升分享点击率

DrawLink:一键生成链接视觉卡片,提升分享点击率

小贴士 :此站或已变迁,但探索不止步。我们已为您备好「类似网站」精选合集,相信其中的发现同样能为您带来惊喜。