JavaScript学习笔记

JavaScript基础

第一章 JS基础语法

1、js定义

JS是基于对象和事件 ,运行在客户端 的、解释性脚本/编程语言

2、js组成部分

  • ES(ECMAScript) 语法规范

  • DOM (document Object Model) 文档对象模型---操作节点

  • BOM (Browser Object Model) 浏览器对象模型

3、JS的书写位置

  • 厚朴培训\各阶段\JavaScript\2023.12.13\01-JS的书写位置.html
①行内
xml 复制代码
<!-- 行内 写在开始标签内	少用 -->
<button onclick="alert('aaa')">
	行内js
</button>
②内部js,写在script标签内
xml 复制代码
<!-- 内部js--写在body 一定要放在要控制的节点下面 -->
<script>
		js代码
</script>

<!-- 内部js--写在head 要获取节点一定要写加载函数 -->
<script>
	window.onload = function() {
		js代码
	}
</script>
③外部js,要写一个js后缀的文件,用script标签引入
xml 复制代码
<!-- 外部js写在head内,要获取节点一定要写加载函数 -->

<!-- 外部js,在body内引入,要写一个js后缀的文件,用script标签引入 -->
<!-- 要放在要控制的节点下面 常用 -->
<script src="js路径"></script>

4、变量

4.1 定义

用来存储数据的容器

4.2 声明和赋值
  • 用var关键字声明,可以先声明后赋值,也可以同时声明和赋值,还可以同时声明多个变量用逗号隔开
javascript 复制代码
ES6新增了 let  const 关键字
let : 声明变量  (存数据的容器,里面的数据可以修改)
const:声明常量(存数据的容器,声明的同时必须赋值里面的数据不可以再重新赋值,
常量里存储的引用类型可以扩展属性和方法的,如果不希望它扩展可以用Object.freeze(对象)来冻结

const obj = Object.freeze({ a: 1 })
obj.b = 2 // b属性没有添加到对象中
console.log(obj);// { a: 1 }


暂时性死区
let 和const 声明的变量/常量 都必须先声明后使用,声明之前的区域被称为暂时性死区
原因:let、const声明的变量\常量 都没有变量、常量的声明提升


 ④同一个作用域内不可以重复声明
 let a = 5;// 全局的作用域
const x = 10
function fn() {
	let a = 5 // 局部作用域
}

if (1) {
	let a = 10; //块级作用域
}

for (let i = 1; i <= 5; i++) { // i 是父级作用域
	let i = 55 // i 是子级作用域
	console.log(i);
}

console.log(i);
fn()
4.3 取名规范
  • 由数字、字母、下划线(_)、美元符号($)来组成
  • 不能以数字开头,不能用关键字、保留字
  • 注意大小写
4.4 作用域/分类
全局变量:
  • 声明在函数,在js中都可以用,始终保存在内存中,用var声明的全局变量也是window的属性
局部变量
  • 声明在函数,只能在该函数内使用
  • 调用函数时生效,未调用函数或函数调用完毕该变量销毁

5、数据类型

5.1 分类
① 值类型/简单数据类型/原始数据类型(6个)
  • null 空
  • undefined 未定义(变量的初始值)
  • number 数字(整数、浮点数、NaN)
  • boolean 布尔(true 真,false 假)
  • string 字符串(凡是用引号引起来的内容)
  • symbol 独一无二的值
②引用类型/复杂数据类型(2个)
  • object 对象
  • function 函数

两种类型的区别

scss 复制代码
(1)值类型存在栈中  引用类型存在堆中

(2)读取
值类型直接从栈中读取    引用类型先从栈中读取地址 在根据地址去堆中找内容


(3)赋值
值类型,直接将内容赋值给新变量  赋值完之后新旧两个变量互相不影响
引用类型  新增加了一个指针 将值和地址都赋值给新变量 赋值完新旧两个变量指向同一个内容  互相影响

(4)传参
实参值类型,直接将内容赋值给新变量  赋值完之后新旧两个变量互相不影响
实参引用类型  将地址赋值给了形参 赋值完之后 形参和实参指向同一个内容 即新增了一个指针 相互影响
5.2 检测 用typeof数据变量名/数据

结果的数据类型都是字符串,具体有7种:

'undefined' 未定义 'number' 数字 'boolean' 布尔 'string' 字符串

'symbol' 独一无二的值 'object' 对象 'function' 函数

5.3 转换
  • 厚朴培训\各阶段\JavaScript\2023.12.13\04-数据类型.html
分为强制转换和弱类型/隐式转换(浏览器自动转换的)

弱类型/隐式转换(浏览器自动转换的)

arduino 复制代码
//减乘除运算遇到纯数字的字符串会将其转换成数字再计算
//加法里将布尔值、null等转换为数字
//"+"任意一边有字符串就会做字符串拼接

强制转换

csharp 复制代码
// 转换成字符串
//1、String(数据)
//2、数据.toString()

//转换成布尔值
// 规律: null、undefined、NaN、0、false、空字符串('')返回false,其余为true
//Boolean(数据)

// 转换成数字型(重点)
// 1、Number(数据)
规律: 
	null、false、空字符串('')、空格字符串('  ')返回0
	true 返回1
	数字、纯数字的字符串返回数字本身
	其余返回NaN
// 2、parseInt(数据)	取整
规律:
	整数、浮点数、纯数字的字符串、以数字开头的字符串 都返回整数部分
	其余返回NaN
// 3、parseFloat(数据)	取浮点数
规律:
	整数、纯数字的字符串、以数字开头的字符串 返回浮点数
	其余返回NaN
5.4 ES6新增的数据类型

①Symbol

②Set

③Map

5.5 ES6新增的迭代器/遍历器
js 复制代码
1、定义/作用
给可迭代的对象提供统一的访问接口,有iterator接口/方法的数据都可以用for...of来遍历

2、迭代器对象
①它本身是一个对象,里面有next方法,next方法又会返回一个结果对象
②结果对象里有两个属性,value表示依次取出的值,done是个布尔值,表示迭代是否结束

3、封装迭代器函数
function makeIterator(arr) {
    let nextIndex = 0;	//存储下标
    return {	//迭代器对象
        next() {
            return nextIndex < arr.length ?
                { value: arr[nextIndex++], done: false }
                :
                { value: undefined, done: true }
        }
    }
}

4、可迭代的对象
看有没有迭代器接口即有没有[Symbol.iterator]接口/方法
默认可迭代的对象:array对象、set对象、map对象、字符串对象
数组	可以用for、for...in、for...of来遍历
普通对象  只能用for...in来遍历,用for...of会报错,因为它没有迭代器接口,不是可迭代的对象
let people = {
    name: 'lele',
    [Symbol.iterator]() {
        return makeIterator(Object.keys(people));	//for...of迭代返回的是属性名
        // return makeIterator(Object.values(people));	//for...of迭代返回的是属性值
    }
}

5、让一个普通对象变成可迭代对象,能用for...of遍历,给这个普通对象加迭代器接口即可
让所有的普通对象都能用for...of遍历,给所有的普通对象加迭代器接口即在Object的原型
对象上添加迭代器接口

6、封装一个判断某个数据是不是可迭代的函数
function isIterable(obj){
    return typeof obj[Symbol.iterator] === 'function';
}

7、用class创建一个类,该类的实例对象都是可以迭代的,for...of遍历时返回键值对,且有判断对象实例是否可以迭代
class fun {
    // 构造函数
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    // 实例共享的方法--原型上的方法
    // 1、迭代器接口
    [Symbol.iterator]() {
        return this.makeIterator(Object.entries(this));  //返回键值对
        // return makeIterator(Object.keys(this));	//for...of迭代返回的是属性名
        // return makeIterator(Object.values(people));	//for...of迭代返回的是属性值
    }
    // 2、判断实例是否可迭代
    isIterable() {
        return typeof this[Symbol.iterator] === 'function';
    }
    // 3、迭代器函数
    makeIterator(arr) {
        let nextIndex = 0;	//存储下标
        return {	//迭代器对象
            next() {
                return nextIndex < arr.length ?
                    { value: arr[nextIndex++], done: false }
                    :
                    { value: undefined, done: true }
            }
        }
    }
}
5.6 生成器
js 复制代码
// 1、定义/作用
// 生成器是一个返回值为迭代器的函数

// 2、写法
// function和函数名中加 * ,函数体内用yield关键字,
// 每次调用next方法执行到一个yield位置就暂停
// 在执行过程中遇到return 就会结束迭代,return的值会作为value,done的值为true
function * generator() {
    yield 1;
    yield 2;
    yield 3;
}
let ite = generator();	//变量ite里存的是迭代器
console.log(ite.next());	//{value:1,done:false}
console.log(ite.next());	//{value:2,done:false}
console.log(ite.next());	//{value:3,done:false}
console.log(ite.next());	//{value:undefined,done:false}
// 3、优化迭代器
class fun {
    // 构造函数
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    // 实例共享的方法--原型上的方法
    // 1、迭代器接口--加*变成生成器
    *[Symbol.iterator]() {
        for(let key of Object.entries(this)) {
            yield key;
        }
        // Object.entries(this);  //返回键值对
        // Object.keys(this)	//返回的是属性名
        // Object.values(people)//返回的是属性值
    }
    // 2、判断实例是否可迭代
    isIterable() {
        return typeof this[Symbol.iterator] === 'function';
    }
    // 3、迭代器函数
    makeIterator(arr) {
        let nextIndex = 0;	//存储下标
        return {	//迭代器对象
            next() {
                return nextIndex < arr.length ?
                    { value: arr[nextIndex++], done: false }
                    :
                    { value: undefined, done: true }
            }
        }
    }
}

6、运算符(js基础第二天)

6.1 算术运算符
css 复制代码
+、-、*、/、%(取余、模)、++(自加)、--(自减)

要点:
+	左右任意一边有字符串,+做字符串拼接,返回一个字符串
-、*、/、%(取余、模)	有隐式转换,数字取余的结果一定是一个非负整数

a++ 等价于 a = a + a,a-- 等价于 a = a - 1;
++、-- 在前表示先自加/减,后赋值
++、-- 在前表示先赋值,后自加/减

js中浮点数的计算会出现误差,可以用toFixed(位数)来保留几位小数,保留是会自动四舍五入且转换为纯数字的字符串
6.2 比较运算符
javascript 复制代码
>、<、>=、<=、==(相等)、!=(不相等)、===(全等)、!==(不全等)

要点:
①比较时会做弱类型转换
②undefined、null、NaN 和 0 比较都是 false
③undefined 和 null,== 为 true,=== 为 false
④NaN == NaN 为false
⑤==只比较值,会做隐式转换,===比较值和类型
⑥比较运算符返回的结果一定是布尔值
6.3 逻辑运算符
scss 复制代码
&&(且/与)		||(或)		!(非/取反)

要点:
①&& 一假则假,全真才真---两边都是真,结果才是真,任意一边为假,结果就为假
①|| 一真则真,全假才假---两边都是假,结果才是假,任意一边为真,结果就为真
③取反返回的结果一定是布尔值
6.4 赋值运算符
css 复制代码
=	右边赋值给左边
+=	a+=5;  等同于  a = a + 5;
-=	a-=5;  等同于  a = a - 5;
*=	a*=5;  等同于  a = a * 5;
/=	a/=5;  等同于  a = a / 5;
%=	a%=5;  等同于  a = a % 5;
6.5 运算符优先级
diff 复制代码
括号一元乘除余,加减比较等不等,先且后或再赋值
()
++ -- !
* / %
+ - 
> < >= <=
== === != !==
&&
||
=

第二章 程序结构

1、定义

又叫流程控制,是指代码执行的顺序

2、分类

2.1 顺序结构

代码从上往下依次执行,绝大多数都是该结构

2.2 分支/选择结构 if switch
二选一
arduino 复制代码
①if...else
if(条件) {
	条件为真执行的代码
}else{
	条件为假执行的代码
}

②三元运算符/条件运算符? :		适用于执行的代码只有1行
条件 ? 条件为真执行的代码:条件为假执行的代码
多选一
arduino 复制代码
①if...else if...else
if(条件1) {
	条件1为真执行的代码
}else if(条件2){
	条件2为假执行的代码
}else if(条件3){
	条件3为假执行的代码
}
....
else {
	以上条件都为假执行的代码
}

②switch
switch(表达式) {
	case 值1 :
	表达式 === 值1为true时执行的代码;
	break;
	case 值2 :
	表达式 === 值2为true时执行的代码;
	break;
	case 值3 :
	表达式 === 值3为true时执行的代码;
	break;
	....
	default:
	表达式和以上三个值都不相等执行的代码
	break;
}
javascript 复制代码
isNaN(数据)判断数据是不是一个非数字,时非数字返回true,不是返回false,一般与分支结构搭配使用

例如:isNaN(5)	 //false  5是一个非数字,对吗?	 //不对 

			isNaN('a')   //true  a是一个非数字,对吗?   //对

3、循环结构 for for...in while do...while

js 复制代码
//定义
在满足条件的情况下,进行重复的操作

//优点
解决重复操作,减少代码编写量,使代码结构清晰,增强代码的可读性

//分类
①for
语法结构:
for(初始条件;判断条件;迭代条件){
    重复执行的代码
}
初始条件:从哪里开始
判断条件:到哪里结束--不满足判断条件时结束
迭代条件:下一次从哪里开始

②for...in	遍历对象
for(var key in 对象名) {
			
		}
//for in的遍历,变量修改无效即不能更改下一次迭代的变量的值

③while			不能确定循环的次数时用
语法结构:
初始条件;
while(判断条件){
    重复执行的代码;
    迭代条件;
}
使用场景:不能确定循环的次数时用while
能用for循环实现的需求都能用while实现,能用while实现的需求for循环不一定能实现

④do...while		先执行一次,再判断,适用至少要执行一次的不确定循环的次数的场景
语法结构:
	初始条件;
	do{
    	重复的执行代码;
        迭代条件
	}
	while(判断条件)
        
⑤跳转语句
break		结束循环,可以用在循环、switch判断、函数
continue	跳过本次循环,后面继续,只能用于循环

//嵌套
for、while、do...while  可以相互嵌套,一般只用两层,称为双层循环
外层循环的变量走一个,内层循环的变量从头到尾走一遍

断点调试

第三章 对象

1、定义

属性方法 组成的无序键值对集合----本质 存数据的容器

  • 属性:特征
  • 方法:能做什么

2、内置对象

  • js封装好的,可以直接使用的对象,常用的内置对象有:Array--数组、Date--日期、Math--处理数学任务、String--字符串
2.1 Array--数组
(1)定义

用单独的变量名来存一系列数据的容器,里面的内容叫元素,可以是任意的数据类型

(2)创建
  • new Array() new调用构造函数

  • \] 字面量---语法糖 常用

  • 数组名[下标] 下标是从0开始----单个

  • 一次性读取数组中多个 元素----循环/遍历

kotlin 复制代码
法1:因为数组是内置对象,可以用for...in来遍历,break、continue依然可用
可以根据需求控制下标来读取对应的元素,若下标对应的元素不存在,默认值是undefined

法2:因为数组有length属性,可以用for来遍历
(4)长度属性

数组名.length 表示数组中元素的个数,从1开始,可读可写

(5)数组分类
  • 密集数组:元素之间无间隔---每个下标对应的元素都有数据 [1,2,9,5,7] for和for...in遍历一样
  • 稀疏数组:元素间有间隔---有的下标对应的元素没有数据 [1,,,,,,4,5] for会遍历每个元素,没有数据的元素返回undefined,for...in只读取有数据的元素
(6)数组的方法
javascript 复制代码
// 1、会改变原数组的方法--7个
(1)增
// 法1:加在末尾  数组名.push(要加的元素1个或多个,用逗号隔开,依次添加)   返回数组的新长度

//法2:加在开头  数组名.unshift(要加的元素1个或多个,用逗号隔开,依次添加)   返回数组的新长度

// 法3:加在指定的位置  数组名.splice(下标,0,要加的元素1个或多个用逗号隔开依次添加)   返回1个空数组

(2)删
// 法1:删末尾  数组名.pop()  返回被删除的元素

// 法2:删开头   数组名.shift()   返回被删除的元素

// 法3:删指定的位置的   数组名.splice(下标,删除的个数)  返回1个数组,里面的元素是被删除的元素
(3)改
// 方法1:数组名[下标] = 新的值

// 方法2:数组名.splice(下标,要改写的个数,改写的新值)  返回1个数组,里面的元素是被改写的元素
(4)倒序   返回倒序后的数组
数组.reverse()
(5)排序
①数组名.sort();   按照0-9,a-z的顺序,先对首位进行排序,首位相同对第二位排序,以此类推

②数组名.sort(function(a,b){return a-b});   对纯数字的数组从小到大
 数组名.sort(function(a,b){return b-a});   对纯数字的数组从大到小
// 2、不会改变原数组的方法--5个
(1)合并
数组名1.concat(数组名2,数组名3...) 返回一个新数组,里面的元素是和并的数组,注意顺序
(2)拼接
拼接   数组名.join('分隔符')   返回一个字符串  分隔符不写默认是逗号
(3)截取
数组名.slice(开始的下标,结束的下标)  返回一个新数组,里面的元素就是按照下标截取的内容,包前不包后
(4)查找   是===判断,注意数据类型,不会进行弱类型转换
数组名.indexOf(要找的元素,开始找的下标)  参数2选写,默认是0,如果找到了返回找到的该元素的下标,没找到返回-1
(5)从末尾往前查找   是===判断,注意数据类型,不会进行弱类型转换
数组名.lastIndexOf(要找的元素,开始找的下标)  参数2选写,默认是数组的length-1,如果找到了返回找到的该元素的下标,没找到返回-1

3、静态方法	Array构造函数的方法
(1)Array.isArray(数据)
判断括号里的数据是不是数组,如果是返回true,不是返回false,一般和分支结构搭配使用

(2)Array.from(数据)
将数据生成一个数组,如果数据是有length属性如字符串或可迭代时会将数据分割为数组的元素,否则返回空数组

(3)Array.of(参1,参2,参3...)
生成一个数组,将每个参数做为数组的元素,不传参返回空数组
kotlin 复制代码
4、实参为函数的方法,该实参函数称为回调函数,该方法称为主函数

语法结构(1-5):
①数组名.方法名(callbackFn,thisVal)--参1(是回调函数)必须写,参2(this的指向)选写
②callbackFn:可以是具名函数的函数名,也可以是匿名函数,参1是数组的每个元素,参2是每个元素的索引,参3是数组对象选写
③thisVal:没传,this 指向 window;传了实参,this 指向 该实参,如果实参是值类型会变成包装类;如果传入的实参是undefined和null,this指向window
④作用:将数组中的每一项都执行一次回调函数,类似for/for...in 但不能用跳转语句break和contiue

1、数组名.forEach(callbackFn,thisVal)
返回值:undefined

2、数组名.map(callbackFn,thisVal)
返回值:新数组(注意map的回调函数里一定要写return)

3、数组名.filter(callbackFn,thisVal)	过滤
返回值:新数组(里面的元素只能是满足条件的,而map的返回值和原数组的长度一致,不满足条件的项会返回undefined)

4、some方法同forEach,区别是some的返回值是布尔值,数组的元素都不满足条件返回false,任意一个满足条件返回true

5、every方法同forEach,区别是every的返回值是布尔值,都满足条件返回true,任意一个条件不满足返回false


语法结构(6-7):
①数组名.方法名(callbackFn,initVal)	参1(是回调函数)必须写,参2(是初始值)选写
②作用:将数组中的每一项都执行一次回调函数,返回计算后的值
③callbackFn:可以是具名函数的函数名,也可以是匿名函数。参1是初始值必写,参2是数组的每个元素必写,参3是每个元素的索引选写,参4是数组对象选写
④initVal:没传,是数组的第1个元素,传了就用传的实参

6、数组名.reduce(callbackFn,initVal)

7、数组名.reduceRight(callbackFn,initVal)
reduceRight从右往左去数组中每一项计算,返回计算后的值
sql 复制代码
拓展
数组名.filter(Boolean);	传入Boolean函数作为参数,将数组中的每个元素作为参数进行求值,空字符串在转换为布尔值时会被视为false,而其他非空字符串会被视为true
(7)扩展运算符
js 复制代码
// 1、扩展运算符
// 定义/作用:将数组或对象里的内容扩展出来为一个序列
// 可以用于合并数组
//可以将数组和可遍历的对象装换成真正的数组
//数组的浅拷贝


let arr = [1, 2, 3, [4, 5]]//数组的浅拷贝
let arrC = [...arr]

function fn() {//可以将数组和可遍历的对象装换成真正的数组
    console.log(arguments);
    let arr = [...arguments]
    console.log(arr);
}
fn(7, 8, 9)
(8)代理---ES6新增
javascript 复制代码
// 1、定义
// 代理(proxy)是指在目标对象前架设一层拦截,外界访问目标对象的信息是代理对象的过滤和修改过的

// 2、语法
// ①创建代理对象
// Proxy是构造函数,new调用实例化代理对象
// 传两个参数,第1个参数是目标对象,第2个参数是拦截对象
// ②拦截读取的函数	get方法
// ③拦截设置的函数	set方法

// 场景:房主要卖房,找中介帮忙,买房的人要通过中介来买房
// 	  目标对象		代理对象	  外界
let owner = {
    name:'lele',
    address:'山湖间五栋2单元301',
    size:'100m²',
    price:120,
    phone:13546816940
}

let p1 = new Proxy(owner,{
    get(target,key){
        if(key == 'price'){
            return owner[key]+=5;
        }else if(key == 'phone'){
            return '我们来联系房主';
        }else if(key == 'name'){
            return '张大帅';
        }else{
            return owner[key];
        }
    },
    set(owner,key,val){
        // if(key == 'price' && val < 130 && val >110){
        // 	owner[key] = val;
        // }
        return false;
    }
})

// 外界
p1.price = 125;
console.log(p1.price);

console.log(p1.price);
// console.log(p1.phone);
2.2 String--字符串
(1)定义

用引号引起来的文本

(2)创建
  • new String() new调用构造函数,创建的数据类型是Object
  • ' '或" " 字面量---语法糖 常用,创建的数据类型是String
(3)读取元素
  • 字符串名[下标] 下标是从0开始----单个

  • 一次性读取字符串中多个 字符----循环/遍历

javascript 复制代码
法1:new String 创建的是字符串,可以用for...in来遍历,break、continue依然可用
可以根据需求控制下标来读取对应的元素,若下标对应的元素不存在,默认值是undefined

法2:因为字符串有length属性,可以用for来遍历
(4)长度属性

数组名.length 表示字符串中字符的个数,从1开始,只可读,一个汉字、字母、空格、数字、字符都占1个长度

(5)方法
scss 复制代码
字符串具有稳定性,所有的方法都不会改变原字符串
1、改大小写,只对字母有效,整体改写   //常用于搜索内容大小写转换---不区分大小写/模糊搜索
① 字符串名.toUpperCase()  改为大写
② 字符串名.toLowerCase()  改为小写

2、截取字符/字符串  重点掌握①②
①字符串名.charAt(索引)  返回索引对应的字符,如没有该索引返回undefined  截取单个字符
②字符串名.slice(开始索引,结束索引)  返回字符串,包前不包后,参数2不写,默认到字符串的length结束
③字符串名.substr(开始索引,结束索引)  返回字符串,包前不包后,参数2不写,默认到字符串的length结束
④字符串名.substring(开始索引,结束索引)  返回字符串,包前不包后,参数2不写,默认到字符串的length结束

3、查找字符  返回索引或-1  严格区分大小写
①查找
字符串.indexOf(要找的字符串/字符,开始找的下标)  参数2选写,默认是0,如果找到了返回找到的该字符串/字符的下标,没找到返回-1
②从末尾往前查找
字符串.lastIndexOf(要找的字符串/字符,开始找的下标)  参数2选写,默认是字符串的length-1,如果找到了返回找到的该字符串/字符的下标,没找到返回-1

4、重复
字符串名.repeat(次数)

5、将字符串分割为数组
字符串名.split('分割符')  //分割符不写默认将字符串整体作为数组的1个元素,写了分割符以该字符切割
例如:var str = 'd g sd'; str.split('');//['a','g','sd']

6、去除首尾空格
字符串名.trim()
(6)正则
less 复制代码
1、定义
匹配模式用于匹配字符串

2、创建
①字面量  /正则内容/修饰符  常用 修饰符:i不区分大小写  g全局匹配
②new RegExp(正则内容)

3、匹配字符串
正则.test(字符串)  	匹配成功  返回true  反之返回false
字符串.search(正则)	匹配成功 返回下标>=0的整数 反之返回-1
字符串.replace(/正则/g,用来替换的内容)  将匹配正则的内容替换为新内容 g表示全局匹配即全部替换
'a1b2c3'.replace(/\d/g,'k'); 返回'akbkck'

4、常用字符
① ^  开头
② $  结尾
③ |  二选一  x | y 匹配x或y
④ [] 多选一  连续范围加- 不包含该范围[]里面加^
  [abc]匹配a或b或c 
  [a-z]匹配任意一个小写字母 
  [A-Z]匹配任意一个大写字母
  [0-9]匹配0-9的任意数字
  [^0-9]不匹配0-9的任意数字
⑤ \d  等价[0-9]  匹配0-9的任意数字
  \D  等价[^0-9]  不匹配0-9的任意数字
  \w  等价[a-zA-Z0-p]  匹配a-z、A-Z、0-9的任意数字
  \d  等价[^a-zA-Z0-p]  不匹配a-z、A-Z、0-9的任意数字

5、常用量词
* 	任意次		>=0
+ 	至少1次	>=1
? 	0次或1次 	==0 || ==1
{n} n次		 ==n
{n,}至少n次	>=n
{n,m} n-m次	 >=n && <=m
(7)表单验证
ini 复制代码
1、表单事件
onfocus  获取焦点/光标
onblur	 失去焦点/光标
onchange 域的内容改变

2、修改节点里的内容
节点.innerText = '新的文本内容'
节点.innerHML  = '新的内容,文本标签都可以'

3、修改节点的样式,多条样式可以放在类名里
节点.className = '类名'
2.3 Math--处理数学任务
(1)、定义

是一个对象,用于处理各种数学任务

(2)属性
javascript 复制代码
Math.PI  返回圆周率
(3)方法
scss 复制代码
(1)取整
①Math.ceil(x)  上舍入,整数返回本身,正的浮点数取整加1,负的浮点数取整
②Math.floor(x)  下舍入,整数返回本身,正的浮点数取整,负的浮点数取整减1
③Math.round(x)  四舍五入,整数返回本身
正的浮点数第一位小数小于5取整,反之加一;
负的浮点数第一位小数小于5取整,反之取整减1

(2)取最大值
①MAth.max(x,y...)  返回最大值
②Math.min(x,y...)  返回最小值

(3)取绝对值
Math.abs(x)  正数和0返回本身  负数返回相反数

(4)计算n次方
Math.pow(x,n)  x的n次方

(5)随机数
Math.random() 返回0-1之间的浮点数,能渠道0,不能取到1
2.4 Date--处理日期和时间
(1)定义

用于处理日期和时间的内置对象构造函数

(2)创建
javascript 复制代码
①当前日期对象
var today = new Date();

②指定的日期对象---过去的或将来的  给构造函数传参
var choic = new Date('2021/10/5/17:40:20')  //过去的时间
var choic = new Date('2055/10/5/17:40:20')  //将来的时间
(3)方法
vbscript 复制代码
set是设置,get是获取
①年  日期对象.getFullYear()  返回当前的年份,4位整数
②月  日期对象.getMonth()  返回0-11
③日  日期对象.getDate()  返回1-31的整数
④星期  日期对象.getDay()  返回0-6的整数  0指的是星期天,1是星期一,以此类推
⑤时   日期对象.getHours()  返回0-23的整数  24小时制
⑥分   日期对象.getMinutes()  返回0-59的整数
⑦秒   日期对象.getSeconds()  返回0-59的整数
⑧毫秒   日期对象.getTime()  返回较大的整数

3、自定义对象

3.1 创建(2023.12.20/01-对象.html)
javascript 复制代码
1、字面量 {}  {}里面放键值对,键的数据类型是字符串,值可以是任意的数据类型  创建单个对象 常用
2、new 构造函数
	①new Object()  很少有
	②new 自定义的构造函数名(传参)  用来创建一系列对象 常用
3.2 属性的增删改查
arduino 复制代码
// 1、增 
// ①对象名.属性名 = 属性值
// ②对象名['属性名'] = 属性值  属性名为数字只能用②

// 2、删   
// ①delete 对象名.属性名   返回布尔值,能删返回true,如删除对象的属性(不管属性有没有),不能删返回false
// ②属性名为数字就用  delate 对象名['属性名']

//3、改写
// ①对象名.要改写的属性名 = 新的属性值  属性名为数字就只能用[]
// 原理:属性名相同,属性值不同时,后一个覆盖前一个
		  
// 4、查看属性值  对象名.属性名  属性名为数字就只能用[]  属性不存在返回undefined
// 查看多个  用for...in遍历
3.3 方法
定义:属性值为函数的属性
查看:对象名.方法名
调用:对象名.方法名(有参数要传参)

第四章 函数

1、定义

  • 为了实现特定功能代码块 ,可以重复调用 //函数具有较好的复用性

2、使用

2.1 声明
基本结构
js 复制代码
//1、独立声明的函数
function 函数名 (参数) { 执行代码块 }
/*function 声明函数的关键字
函数名 可以选写  命名规范同变量
参数:可以选写  根据项目需求来写
执行代码块:实现特定的功能*/

//2、函数表达式
var 变量名 = function (参数) { 执行代码块 }
2.2 调用
js 复制代码
//1、独立声明的函数   可以先声明后调用,也可以先调用后声明
调用:函数名(有参数要传参)

//2、函数表达式   只可以先声明后调用
调用:变量们(有参数要传参)

注意:函数一定要调用才生效,函数声明在哪里不重要,在哪里调用很重要

3、分类

(1)有无函数名
  • 具名/有名函数

    独立声明的函数一定要取函数名

  • 匿名函数

    ①函数表达式

    ②事件触发时 = 右边的函数
    一定有 = 符号

(2)有无参数
  • 无参函数
scss 复制代码
声明时()里没有参数
  • 带参/有参函数
js 复制代码
声明时()里有参数,参数及其个数取决于项目需求
①形参:声明时()里的参数,本质是变量,没传实参默认是undefined
②实参:调用时()里的参数,本质是确定的值
③传参方向:将实参传给形参
④传参顺序:一一对应(实参1传给形参1,实参2给形参2.......)
⑤传参个数:尽量保持一致(有几个形参就传几个实参)

//实参列表  arguments  是一个伪数组,typeof arguments返回'object'
//能将实参依次放在里面,读取arguments[下标],也可以用for遍历,但不能用数组的方法
//可以在函数声明内:用arguments[下标] = 新的值 来修改实参的值
(3)有无返回值
  • 返回值为默认值undefined的函数
kotlin 复制代码
函数声明内没有 return 关键字 
  • 带特定返回值的函数
kotlin 复制代码
喊声声明内最后一行一定要 return 关键字
当函数的调用结果后续要进一步处理就一定要放返回值
return后默认返回一个值,要返回多个值,用数组或者对象(常用)  具体见:2023.12.25/01.html的计算两数和

4、封装

将相同的逻辑复制到函数中,不同的内容提取为参数,调用时传参

第五章 DOM操作

1、DOM基础操作

1.1 获取节点
js 复制代码
1、使用js内置的方法
document.getElementById('id名')  	    获取一个具体的节点
document.getElementsByClassName('类名')  获取一个集合,获取具体节点 集合名[下标]
document.getElementsByTagName('标签名')  获取一个集合,获取具体节点 集合名[下标] 范围大 整个页面
父节点.getElementsByTagName('标签名')  	获取一个集合,获取具体节点 集合名[下标] 范围小 父节点里面
document.getElementsByName('name名')    获取一个集合,获取具体节点 集合名[下标]
document.querySelector('css选择器')  	  获取一个具体的节点  是满足该css选择器的第1个节点
document.querySelectorAll('css选择器')   获取一个集合,获取具体节点 集合名[下标]

2、通过层级关系来获取
子节点.parentNode  获取父节点,要获取祖先就不断往上找即链式写法增加parentNode,最终找到document文件,再往上是null
父节点.firstElementChild  获取父节点里的第1个标签子节点
父节点.lastElementChild  获取父节点里的最后1个标签子节点
弟节点.previousElementSibling  获取兄节点
兄节点.nextElementSibling  获取弟节点
1.2 属性操作
arduino 复制代码
1、获取属性值
①节点.属性名  类名用className
②节点.getAttribute('属性名') name的值只能用它获取

2、设置属性或修改属性值
①节点.属性名 = '属性值'  类名用className
②节点.setAttribute('属性名','属性值')
1.3 内容操作
ini 复制代码
1、获取
①节点.innerText  只获取文本内容
②节点.innerHTML  获取标签和文本

2、设置和修改
①节点.innerText =  '新的文本内容'
②节点.innerHTML =  '新的标签和文本'
会覆盖原来的内容,可以赋空字符串用来清空里面的内容,要保留原来的内容在赋值时把原来的内容重新写一遍
1.4 样式操作
csharp 复制代码
1、行内样式  弊端:①结构和表现未分离,不利于维护;②行内样式优先级高,类样式回不去
①单条  节点.style.样式名 = 样式值   //有'-'的样式名改为驼峰命名
②多条  节点.style = '样式名1:样式值1;样式名2:样式值2;样式名3:样式值3;.......'

2、通过类名来设置样式
①节点.className = '类名'  多个类名之间用空格隔开 如:节点.className = 'one two three'
②节点.setAttribute('class','类名')  多个类名之间用空格隔开
③节点.classList.add('类名') 添加类名  追加的效果不会覆盖
④节点.classList.remove('类名')  移除指定的类名
⑤节点.classList.toggle('类名')  切换该类名,如果有就移除,没有就添加
⑥节点.classList.replace('旧类名','新类名')  替换,用新的换旧的
⑦节点.classList.contains('类名')  节点中有没有该类名,有返回true,没有返回false

2、DOM节点操作

2.1 创建节点
ini 复制代码
①document.write('完整标签');  往文档里添加  很少用  了解

②节点.innerHTML = '完整标签';  往节点添加子/后代标签  掌握

③document.createElement('标签名');  创建该标签名的空标签,需要用添加的方法加到页面中才能显示  掌握

④节点.cloneNode();  克隆该节点  掌握
()里不传参只克隆节点标签本身,传true表示克隆节点及里面的内容,克隆好的节点需要用添加的方法加到页面中才能显示
2.2 添加节点
ini 复制代码
①父节点.appendChild(子节点);

②父节点.insertBefore(要插入的节点,指定节点);  要插入的节点插入后是指定节点的兄节点
2.3 删除节点
ini 复制代码
(1)清空节点里的内容,节点标签本身保留
①节点.innerText = '';
②节点.innerHTML = '';

(2)删除父节点内指定子节点
父节点.removeChild(指定子节点);

(3)删除节点本身及内容
节点.remove();
2.4 替换节点
scss 复制代码
父节点.replaceChild(用来替换的节点/新节点,被替换的节点/旧节点)

3、DOM事件操作

3.1 事件三要素
复制代码
(1)事件源:操作的dom节点			获取节点
(2)事件内行:绑定的事件名		   绑定事件
(3)处理程序:触发时间后执行的函数	执行函数
3.2 常用的事件
swift 复制代码
(1)鼠标事件		11个
单击左键	onclick
双击左键	ondblclick
右键菜单	oncontextmenu
滚轴/滚动条	onscroll
移入		onmouseover
移出		onmouseout
移动		onmousemove
按下		onmousedown
松开		onmouseup
进入		onmouseenter
离开		onmouseleave

(2)键盘事件		2个
按键按下		onkeydown
按键松开		onkeyup

(3)表单事件		5个
获得焦点/光标		onfocus
失去焦点/光标		onblur
域的内容改变		onchange
重置		onreset
提交		onsubmit

(4)界面/UI事件
加载界面/图片		onload
界面大小变化		onresize
3.3 event当前时间对象
vbnet 复制代码
定义:
事件触发后,储存事件相关信息的集合

写法:
事件源.事件名 = function(){
	console.log(e);  //e 等价于event
	执行代码
}

常用属性和方法:
①事件源/DOM节点
event.target
②事件类型/事件名
event.type		返回的是事件名不带on
③鼠标位置
event.clientX		横坐标
event.clientY		纵坐标
④按键
event.key 返回按键的字符串
event.keyCode 返回按键码数字

方法:
阻止默认行为	event.preventDefault()	还可以在函数最后加return false;
阻止冒泡	event.stopPropagation
3.4 绑定事件的方式
scss 复制代码
1、行内绑定事件,调用函数,注意函数必须是全局函数
<div onclick='fn()'>11</div>

2、节点.事件名 = 处理函数
①pNode.onclick = function(){执行代码}  =右边是匿名函数
②pNode.onclick - fn  右边是具名函数的函数名,该函数只能是无参函数
function fn(){
	执行代码
}

3、事件监听  节点.addEventListenet('事件名不带on',处理函数,布尔值选传)
事件监听的优点:
①同一个节点绑定相同事件,执行不同的处理函数时,都能执行
②用事件监听绑定的事件可以移除  节点.removeEventListener('事件名不带on',处理函数)
3.5 事件流
lua 复制代码
1、定义
页面接收事件的顺序

2、分类
①事件冒泡  从内层节点往外层节点冒泡---从内往外  浏览器默认支持  阻止冒泡 event.stopPropagation()
②事件捕获  从外层级节点往内层节点捕获---从外往内  事件监听来绑定,第3个参数传true

3、DOM二级事件流---这个节点上既有冒泡又有捕获
先捕获-->目标节点-->冒泡节点
3.6 事件委托
javascript 复制代码
1、定义
利用事件冒泡的原理,将事件绑定给父级(this),操作子级节点(event.target),通过冒泡触发父级节点上绑定事件

2、优点
①事件委托效率更高(运行速度快、易于维护)  
开始计时:console.time('记号') 结束计时:console.timeEnd('记号') 统计代码执行花费的时间
②对于动态添加的子级节点事件依然有效

第六章 BOM操作

1、定义及组成

浏览器对象模型,核心对象是window对象,包含history、location、document

2、window的属性和方法

js 复制代码
1、属性
console.log(window.innerHeight);  //窗口文档高度,返回一个数字没有单位
console.log(window.innerWidth);  //窗口文档宽度,返回一个数字没有单位
			
console.log(window.outerHeight);  //窗口高度,返回一个数字没有单位
console.log(window.outerWidth);    //窗口宽度,返回一个数字没有单位
			
console.log(window.name);  //返回window的名称,没有取名默认是空字符串
			
console.log(window.pageXOffset);  //离左上角 x的距离,返回一个数字没有单位
console.log(window.pageYOffset);  //离左上角 y的距离,返回一个数字没有单位

2、方法  window的方法,可以省略window
① 三种弹窗---会阻塞进程
window.alert(111)  //等价于alert(111) 警示框 只有一个确定按钮,点确定返回undefined
prompt()  //输入框  有一个input框,一个确定一个取消按钮,点确定返回input里的内容,点取消返回null
confirm()  //确认框  一个确定一个取消按钮,点确定返回true,点取消返回false

② 2个定时器/计时事件
setInterval(匿名函数/具名函数函数名,毫秒数) //开定时器,每隔多少毫秒就会执行一次函数---水滴石穿
clearInterval(定时器的id/变量名)
			
setTimeout(匿名函数/具名函数函数名,毫秒数)  //开定时器,等待多少毫秒后执行一次函数---定时炸弹
clearTimeout(定时器的id/变量名)

3、this指向

this是一个关键字,谁调用this,this就指向谁

js 复制代码
1、this指向window
①console.log(this);  //默认情况下(直接打印this),this指向window
②fn();  //直接调用函数,等价于window.fn(),把window省略了,但仍是window调用fn函数,this指向window
③<!-- 行内绑定事件调用函数,等价于window.fn()-->
<button onclick="fn()">按钮1 行内调用</button>
④匿名函数内调用函数
btn2.onclick = function(){
	fn();  //匿名函数内调用函数 等价于window.fn()
}
btn2.addEventListener('click',function(){
	fn();  //匿名函数内调用函数
})
⑤定时器里的this
setInterval(function(){
    console.log(this);
},1000)
⑥立即执行函数里的this
(function(){console.log(this);}())

2、this指向具体的节点
①调用具名函数的函数名
btn2.onclick = fn;  //调用具名函数的函数名,this指向事件左边的对象,即具体的标签的节点
btn2.addEventListener('click',fn);  //调用具名函数的函数名,this指向事件监听左边的对象
②匿名函数内直接使用this
btn2.onclick = function(){
    console.log(this);
}
btn2.addEventListener('click',function(){
	console.log(this);
})

③对象里的this一般指向该对象

④构造函数、原型里的this都指向具体的实例对象

function fn(){
	console.log(this);
}
改变this的指向
kotlin 复制代码
(1)要改变this指向的函数,call(this的新指向,实参1,实参2...)
(2)要改变this指向的函数,apply(this的新指向,[实参1,实参2...]) apply的参数2是数组
(3)要改变this指向的函数,bind(this的新指向,实参1,实参2...)()	bind一定要加()调用
当内外函数里的this指向不同时,内函数要用外函数里的this指向,可以将外函数里的this指向存储到变量中,内函数用该变量即可

4、location对象

控制地址URL---统一资源定位符,包含协议、主机名/域名、端口(可省略)、路径

4.1 属性

location.host 返回主机名和端口名

location.hostname 返回主机名

location.href 返回完整地址

location.href = '完整的地址' 设置新的地址,会自动跳转到该地址的页面

4.2 方法

location.reload() 重新加载该页面/刷新

location.replace('完整地址') 将当前页面替换为完整地址对应的新页面

5、history对象

方法

①history.forward() 前进 等价于 history.go(1)

②history.back() 后退 等价于 history.go(-1)

6、document对象

既是DOM对象,也是BOM对象里的一部分

属性

①document.URL 获取当前文档的完整地址,等价于 location.href

②document.referrer 获取当前文档的来源文档的完整地址

JS高级

第一章 对象扩展

1、构造函数

kotlin 复制代码
(1)用来创建对象的,首字母大写,用关键字new调用,可批量创建对象,且能看到对象的类型

(2)new调用构造函数的过程
①在构造函数内隐式创建this对象		// var this = {};	//隐式创建
②将属性和方法都赋值给this对象		//this.键 = 值;
③函数末尾隐式返回this对象			 // return this;		//隐式返回
④实例化对象时,将this赋值给它		new 函数名(参数1, 参数2)

(3)构造函数里的this,指向具体的实例化对象

(4)通过 原型对象.constructor 来获取 原型对象可以是显式原型也可以是隐式原型
var dog = new Anima('dog');
console.log(dog.__proto__.constructor);  //Anima函数体
console.log(Anima.prototype.constructor);  //Anima函数体
console.log(dog.__proto__.constructor === Anima.prototype.constructor); //true

2、原型

javascript 复制代码
(1)定义
每个函数都有一个prototype的属性,它指向一个对象,称为原型对象

(2)作用
相同的属性和方法放在原型对象中,实例化对象时不会重复创建该属性和方法,会直接从原型上集成,可以节省资源

(3)写法
①构造函数名.prototype.属性名/方法名 = 属性值/函数体

②构造函数名.prototype = {
	constructor:构造函数名,	//将原型对象的构造函数手动指回,不设置指向Object
	相同的属性和方法的键值对
}

(4)原型里的this指向具体的实例化对象

3、静态、实例成员

kotlin 复制代码
1、静态成员--构造函数本身的属性和方法 
使用时:构造函数名.属性名/构造函数名.方法名()

2、实例成员--构造函数内赋值给this的属性和方法 及其原型里的属性和方法
使用时:实例化对象名.属性名/实例化对象名.方法名()

4、对象实例的原型

javascript 复制代码
1、定义
对象实例的原型:每个对象实例都会有__proto__的属性,它指向一个对象,称为实例的原型对象/隐式原型

2、获取
①对象实例名.__proto__ (少用,已被废弃);
②Object.getPrototypeOf(对象实例名)(多用)

3、对象实例的原型和构造函数的原型对象指向同一个对象,即它两等价的
构造函数名.prototype === Object.getPrototypeOf(对象实例名)  返回true

5、原型链

ini 复制代码
1、原型链创建及查找
function 函数名1(参数) {
	this.键名 = 参数;
}
var 实例1 = new 函数名1(传参);

函数名2.prototype = 实例1;	//函数2的原型继承实例1
function 函数名2() {}
var 实例2 = new 函数名2();		

函数名3.prototype = 实例2;	//函数3的原型继承实例2
function 函数名3(参数) {
	this.xing = 参数;
}

var 实例3 = new 函数名3('传参');
console.log(实例3.xing);

2、原型链从下往上查找,最早找到null
console.log(实例对象.__proto__);

6、继承

javascript 复制代码
一、原型链继承
console.log('原型链继承--开始');
		//父类原型的原型上,放父类实例共享的属性和方法
		Fu.prototype.a = 1;

		// 父类构造函数
		function Fu(){}

		// 子类构造函数
		function Son(){}

		// 核心代码:将父类实例赋值给子类的原型
		Son.prototype = new Fu();		

		//实例化子类对象
		var s1 = new Son();
		// 子类实例的a属性从子类的原型上继承的,子类的原型是一个父类的实例,
		// 父类实例的a属性从父类的原型上继承
		console.log(s1.a); //1 
		s1.a = 10;
		console.log(s1.a);
console.log('原型链继承--结束');
弊端:属性值是引用类型,修改一个实例上的属性后会影响原型上该属性

二、借用继承
console.log('借用继承--开始');
	Fu.prototype.obj = {a:19};
	// 父类构造函数
	function Fu() {
		this.arr = ['a','b'];
	}
	// 子类构造函数
	function Son() {
		// 核心代码:将父类构造函数的this从原来指向父类实例改为指向子类实例,
		// 		    因为子类构造函数里的this指向子类实例的
		Fu.call(this);
	}

	var s1 = new Son([1,2,3]);
	console.log(s1.arr);
	s1.arr.push(4); //修改子类实例的属性不会影响父类的属性
	console.log(s1.arr); //['a','b',4]
	console.log(s1.obj); //undefined

	var s2 = new Son();
console.log('借用继承--结束');  //['a','b']

优点:解决了原型链继承的弊端
弊端:
①每次实例对象都会创建父类副本影响性能
②只能继承父类实例的属性和方法,不能继承父类原型上的属性和方法

三、组合继承(原型链继承+借用构造函数继承)
核心:1. 在子类的构造函数中,借用父类的构造函数并改变其this指向 例如:Fu.call(this);
	 2. 将父类实例赋值给子类的构造函数的原型上 例如:Son.prototype = new Fu();
	 3. 将子类的原型constructor属性重新赋值为子类的构造函数 例如Son.prototype.constructor = Son;

7、对象的方法

js 复制代码
一、静态方法
(1)object.getownPropertyDescriptor(对象名,属性名)
作用:返回一个对象,它获取指定属性的描述
代码:
var obj = {a:1};
var res = object. getownPropertyDescriptor(obj,'a');
console. log(res);// {value: 1,writable: true, enumerable: true, configurable: true}

(2)Object.assign(目标对象,源对象1,源对象2...)
作用:所有可枚举属性的值从一个或多个源对象复制到目标对象,它将返回目标对象
代码:
var target = { a: 1, b: 2, c: 666 }
var source = { c: 3, d: 4 }
var assignObj = Object.assign(target, source);
console.log(target);  //{a:1,b:2,c:3,d:4}  合并对象时目标对象会被改变
console.log(assignObj);  //{a:1,b:2,c:3,d:4}

(3)Object.create('对象名')
作用:创建一个新对象
代码:
var obj = {
	a: 1
}
var o = Object.create(obj);
console.log(obj);
console.log(o);

(4)Object.entries('对象名')
作用:返回一个给定对象自身可枚举属性的键值对数组
代码:
var obj = {name:"zhang",age:100,sex:"male"};
console.log(Object.entries(obj)); // [ ["name", "zhang"], ["age", 100], ["sex", "male"] ]

(5)Object.getOwnPropertyDescriptor(对象名,属性名)
作用:返回指定对象上自有属性对应的属性描述符(自有属性即直接赋予该对象的属性,不需要从原型链上进行查找的属性)
代码:
var obj = {
	name: "lucy"
}
console.log(Object.getOwnPropertyDescriptor(obj, "name"));
console.log(Object.getOwnPropertyDescriptor(obj));
对象名必须写,属性名选写

(6)Object.getOwnPropertyNames(对象名)
作用:返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组
代码:
var obj = { a: 1, b: 2, c: 3 }
console.log(Object.getOwnPropertyNames(obj));
//["a","b","c"]
obj.__proto__.d = 4;
console.log(Object.getOwnPropertyNames(obj));
//["a","b","c"]

(7)Object.keys(对象名)
作用:返回一个由一个给定对象的自身可枚举属性组成的数组
var obj = {a: 1,b: 2,c: 3}
Object.keys(obj);// ["a","b","c"]
var o = Object.create(obj);
o.name = "oooo";
Object.keys(o);// ["name"]

Object.getOwnPropertyNames(对象名) 和 Object.keys(对象名) 的区别:
①使用for..in循环时:返回的是所有能通过对象访问的、可枚举的属性(包括存在于实例中的属性、存在于原型中的属性)
②Object.keys()获取对象自身所有的可枚举的属性值,不包括原型中的属性,返回一个由属性名组成的数组
③Object.getOwnPropertyNames()返回对象的所有自身属性的属性名(包括不可枚举的属性)组成的数组,会获取原型链上的属性

(8)Object.getPrototypeOf(对象名)
作用:返回指定对象的原型
代码:
var protoobj = {};
var obj = Object.create(protoobj);
console.log(Object.getPrototypeOf(obj) === protoobj);// true
console.log(Object.getPrototypeOf(obj) === obj.__proto__);// true

(9)Object.setPrototypeOf(对象名)
作用:设置一个指定的对象的原型为另一个对象或null
代码:
var obj = { a: 1 }
console.log(Object.setPrototypeOf(obj, { b: 2 }));
javascript 复制代码
二、实例方法
(1)对象名.hasOwnProperty(属性名)
作用:返回一个布尔值,是指对象自身是否具有指定的属性,自己有返回true,否则返回false,不包含继承的属性
代码:
var obj = {a:1};
console. log(obj.hasownProperty('a')); //true

hasownProperty()方法会返回一个布尔值,指对象自身是否具有指定的属性

(2)对象名.isPrototypeOf(对象名)
作用:判断当前对象是否在传入的参数对象的原型链上
代码:
var MyObj = function(){};
var obj = new MyObj();
//判断Object的prototype是不是在obj的原型链中
console.log(Object.prototype.isPrototypeOf(obj));  //true  

(3)对象名.propertyIsEnumerable('属性名')
作用:判断给定的属性是否被for..in遍历出来,返回布尔值
代码:
var obj = {
	name:'王'
}
for(var key in obj){
	console.log(key);
}
console.log(obj.propertyIsEnumerable('contructor'));  //false
console.log(obj.propertyIsEnumerable('name'));  //true

原因:输出了name属性,但是obj属性很多,遍历了但是没有把contructor等遍历出来

(4)对象名.toLocaleString()	
作用:返回对象的字符串表示,和代码的执行环境有关
代码:
var obj = {};
console.log(obj.toLocaleString());  //[object Object]	
var data = new Date();
console.log(data.toLocaleString());  //2024/1/20 17:07:43  具体的时间

(5)对象名.toString()	
作用:返回对象的字符串表示
代码:
var obj = {};
var data = new Date();
console.log(obj.toString());  //[object Object]
//toLocaleString()和toString()的比较
console.log(data.toLocaleString());  //2024/1/20 17:07:43  具体的时间
console.log(data.toString());  //Sat Jan 20 2024 17:11:27 GMT+0800 (中国标准时间)

(6)对象名.valueOf()
作用:返回对象的原始值,根据对象的不同,返回的可能是字符串、数值或boolean值等
代码:
var arr = [1];
console.log(arr.valueOf());//[1]

var date = new Date();
console.log(date.valueOf());//1456638436303
// 自定义valueOf方法,可以更改返回对象的原始值
arr.valueOf = function(){return false;}
console.log(arr.valueOf());  //false

// ①没有重新定义toString与valueOf时,
// 函数会隐式转换调用默认的toString方法,会将函数的定义内容作为字符串返回。
function fn(){
	return 20;
}
console.log(fn +10);  //函数的原始值
// ②主动定义了toString()/vauleOf()方法时,会返回自定义的值,
// 但是其中valueOf()会比toString()后执行
function fn(){
	return 30;
}
fn.toString = function(){
	return 10;
}
fn.vauleOf = function(){
	return 5;
}

console.log(fn +10);  //20

(7)对象名.watch('属性名')	对象名.unwatch('属性名')	//最好不用
作用:监视传入属性是否被赋值并在赋值时运行相关函数

第二章 JS运行过程、作用域/链、闭包

1、js运行过程

1.1 三步走

语法分析---预编译---执行

1.2 预编译
typescript 复制代码
(1)当js执行前一刻会生成GO--global object对象,当函数执行的前一刻会生成AO--active对象

(2)预编译是将变量声明和函数声明进行提升
GO对象里放全局的变量(初始值undefined)和全局函数(初始值是函数体)
AO对象里放局部的变量(初始值undefined)、形参(初始值是undefined)、局部函数(初始值是函数体)

(3)同一个作用域内函数名和变量名不要重名,如果重名了,函数优先于变量

2、作用域、作用域链

作用域:执行器上下文对象集合、分为全局作用域、局部作用域、块级作用域

作用域链:作用域是一个链式的连接,查找从作用域链的顶端开始往下查找

ES5中用立即执行函数来模拟块级作用域,ES6中用let、const声明的变量/常量实现块级作用域

js 复制代码
// 语法 直接调用  会立即执行{}里的代码
//推荐
(function (x) {
	console.log(x);
}(10));

(function (a, b) {
	console.log(a + b);
})(5, 10);
		
// 需求:点击li 弹出它的下标
// for + 立即执行函数--模拟块级作用域
for (var i = 0; i < LiAll.length; i++) {
	(function (suo) {
		LiAll[i].addEventListener('click', function () {
			console.log(suo);
		})
	}(i))
}

3、闭包

3.1 定义

闭包是能读取其它函数内变量的函数,即在函数外读取函数内的变量需要闭包--内部函数

3.2 基本写法
scss 复制代码
function wrap(){
	var b = 3; //在外函数内声明一个局部变量
	function inner(){ //在内函数里面对局部变量进行操作
		console.log(b);
	}
	return inner;//将内函数的函数体作为外函数的返回值
}
var res = wrap();//调用往爱函数,它的返回值是内函数的函数体存到变量res中
res();//调用内函数的函数体
console.log(res);	//内函数的函数体

4、高阶函数

4.1、定义

高阶函数是一个接收函数作为参数(回调函数的主函数)或者将函数作为返回值输出的函数(闭包里的外函数)

如:定时器、数组遍历的方法----forEach/map/filter...

第三章 深浅拷贝

1.定义

深浅拷贝是针对引用类型,一层引用类型的数据省钱拷贝后

深浅拷贝后相互都不影响

多层引用类型的数据---如对象的属性值又是一个对象或数组 二维/三维...

浅拷贝:拷贝后的对象和被拷贝的对象 相互还是影响

深拷贝:拷贝后的对象和被拷贝的对象 相互独立,不会影响彼此

2、浅拷贝

scss 复制代码
(1)拷贝对象({},[])
//法一遍历
 function cloneObj(){
            var cloneObj=Array.isArray(obj)?[]:{};//判断是不是一个数组或者对象
            for(var k in obj){
                cloneObj[key] = obj[key];
            }
            return cloneObj;
        }
//法二扩展运算符
   function cloneObj(obj){
            var cloneObj=Array.isArray(obj)?[...obj]:{...obj};//判断是不是一个数组或者对象
            return cloneObj;
       }


//法三
 function cloneObj(obj){
            var cloneObj=Array.isArray(obj)?[]:{};
            Object.assign(clone,obj)
            return clone;
    }

3、 深拷贝

js 复制代码
var deepClone = JSON.parse(JSON.stringify(obj));
// 深拷贝的法1:用JSON的方法
// 优点:简洁  弊端:无法拷贝函数/对象的方法  适用场景拷贝的内容里没有function
var deepClone = JSON.parse(JSON.stringify(obj));

// 深拷贝的法2:递归
// 函数功能:深拷贝
// 参数:obj  被拷贝--原对象  数据类型:数组/对象
// 返回值:拷贝后的内容
function deepClone(obj) {
// 1、判断传的实参是不是引用类型--数组、对象,如果不是就抛出错误结束函数
//!obj表示传的实参是null时也不符合参数要求
if (!obj || typeof obj != 'object') {
	throw new Error('传的实参不是数组或对象,请重新传参');
}
// 2、判断传入的实参是数组还是对象,从而确定拷贝后的初始值是对象还是数组
var targetObj = Array.isArray(obj) ? [] : {};
// 3、for...in遍历依次取出每个键对应的值
for (var key in obj) {
	// 4、判断属性/键是不是对象自己的属性,如果是才拷贝
	if (obj.hasOwnProperty(key)) {
	// 5、判断值是什么类型,如果是引用类型就要再次调用该函数克隆里面的内容
	// 如果是原始类型就直接赋值给拷贝后的对象
		if (typeof obj[key] == 'object' && obj[key]) {			 			//obj[key] 排除null
			targetObj[key] = deepClone(obj[key]);
		} else {
			targetObj[key] = obj[key];
		}
	}
}
// 6、返回拷贝后的对象
return targetObj;
}

//深拷贝的法3:用插件(别人封装好可以直接用的js)里的方法
①lodash.js 里的_.deepClone()里的方法
②jquery里的  $.extend(true,target,object1,[objectN]);

4、 异常处理机制

js 复制代码
// try里的代码有错误会执行catch里的代码且不阻塞进程(后面的代码会继续执行) // 只适用于处理无法预测的错误
try{
	可能会发生无法预测的错误的代码
}catch(e){	//当try里的代码有错误,执行了catch的代码
	console.log(e);  //放的是error对象
}
// finally是根据需求选写
finally{
	console.log('不管执行try里面的还是执行catch里的代码,执行之后都会执行finally里的代码');
}

//throw new Error("错误的提示信息");抛出一个错误,同浏览器的报错一样会阻塞进程

第四章 事件循环

1、名词

lua 复制代码
1、宿主环境:运行环境	js的宿主环境是浏览器、node.js
2、进程	CPU--工厂	进程--车间	电脑可以运行多个进程,每个进程包含多个线程
3、线程	线程--工人 浏览器是多进程的,每个标签页是一个进程
4、重绘	修改节点的颜色样式,会重新绘制该节点,比较节省性能
5、重排	也称为回流,修改节点的尺寸、大小、层级关系、数量的增加或减少

2、渲染进程--浏览器内核

2.1 主流浏览器

IE(edge) 、谷歌(chrome)、火狐(fireFox)、欧朋(opear)、苹果(safari)

2.2 内核--(渲染引擎+js引擎)

谷歌(chrome) webkit--->blink V8

2.3 包含的线程
scss 复制代码
(1)GUI渲染线程:页面渲染、交互等
(2)JS引擎线程(js主线程):执行js代码
(3)事件触发线程:控制事件的触发和执行
(4)定时器触发线程:控制setInrerval和setTimeout
(5)异步http请求线程:处理ajax的请求
2.4 渲染流程
scss 复制代码
(1)解析html,生成DOM树
(2)解析css,生成style树,和DOM树合并生成渲染render树
(3)布局 layout
(4)绘制 paint
(5)显示到页面

3、同步异步

arduino 复制代码
1、定义
js任务分为同步任务和异步任务
同步任务:一个时间点只能执行一个任务,即上一个任务执行完毕才会执行下一个任务,会阻塞进程 如弹窗
异步任务:无需等待上一个任务执行完毕,可以同时执行下一个任务

2、使用异步的场景
需要等待的情况都要用异步任务
常见场景:定时任务、ajax请求、事件

3、js任务执行机制
栈:先入后出,后进先出
堆:先进先出,后进先出
①限制性同步任务,再执行异步任务
②同步任务按照代码书写顺序从上往下依次执行,异步任务按照结束等待状态来依次执行的

4、宏任务和微任务
异步任务分为宏任务(2个定时器)和微任务(宏任务执行过程中产生的回 promise.then())

4、执行机制

主线程将同步代码放进执行栈中执行,异步代码放进任务队列中监听,当执行栈中为空,

js主线程才会将任务队列中的代码拿进执行栈中执行,这个过程就是事件循环

4.1 任务队列
  • 宏队列:事件、定时器、网络
  • 微队列(类似VIP):Promise、MutationObserver(监听DOM对象变化)

5、防抖和节流函数

定义:为了限制函数的触发次数,减少浏览器性能的小号,多用于高频发的触发事件中

防抖函数:指频繁触发情况下,只有空闲足够的时间,才能执行一次函数

节流函数:一定时间内函数只执行一次

插件:underscore.js

6、ES6新增的promise对象

arduino 复制代码
//1、定义、作用
// Promise是Es6新增的,用于处理异步任务层层嵌套/回调地狱的问题
// 本质是一个容器,用来存储未来才会结束的异步任务的结果
//语法上Promise是一个构造函数,用于创建一个promise对象
// 2、创建
// new Promise(回调函数)

// 3、promise的3种状态 2种变化
// 状态:pending(进行中)、fulfilled/resolved(已成功)和rejected(已失败)
// 2种变化  pending(进行中)--->fulfilled/resolved(已成功)
//pending(进行中)---->rejected(已失败)
// 状态发生变化后不可逆,也不可改
// 4、实例的方法:then、catch、	finally
// ①他们都是实例的方法,then和catch都会返回新的promise对象,支持链式写法,finally总是返回原来的值
// ②他们都是主函数,调用时里面传回调函数,成功promise的状态时调用then里的回调函数,失败是会调用catch里的
//  回调函数,无论成功还是失败会调用finally里的回调函数
// ③一旦执行了then里的回调函数,就不会执行catch里的回调函数

// 5、静态方法:resolve,reject,all,race

// 6、简化写法  用关键字 async await
// async放在函数(函数声明或函数表达式)的开头,该函数一定会返回promise对象
// await 等待  用于等待一个promise对象,只能用在有async修饰的函数内

第五章 算法

1、定义

解决问题的方案/步骤/过程/思路,使用空间复杂度(运行时占用的空间越少越好)和时间复杂度(运行花费的时间越短越好)来衡量一种算法的优劣

2、常见的排序算法
2.1 冒泡排序/泡排序/起泡排序

**核心思想:**遍历数组,比较相邻的两个元素,前一个大于后一个就交换位置

算法步骤:

①循环/遍历数组,确定循环的次数--即需要循环几轮

②循环数组,依次取出相邻的两项

③比较相邻的两项,如果前一项大于后一项就交换位置

重复②③知道数组全部拍好顺序

代码:

js 复制代码
function bubbleSort(arr){
    for(var i=0;i<arr.length-1;i++){ //外循环  确定循环的次数--即需要循环几轮
        for(var j=0;j<arr.length-1-i;j++){                                                                                                        //内循环 取元素
            if(arr[j]>arr[j+1]){
                var tmp = arr[j]; 
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
            }
        }
    }
    return arr;
}
2.2 归并排序,也称二分法排序

**核心思想:**将数组一分为二,分别对左边和右边的部分进行排序,左右二部分排序之后再合并为一个又循的数组

算法步骤:

①找到中间项,将数组一分为二

②对左边的部分进行排序,重复①

③对右边的部分进行排序,重复①

④左右二部分排序之后再合并为一个又循的数组

代码:

scss 复制代码
function mergeSort(arr, start, end) {
    // 递归的出口
    if (start > end) {
        return []
    } else if (start == end) {//只剩一个
        return [arr[start]]
    } else if (start == end - 1) {//只剩二个,比较二个元素的大小并排行顺序
        return arr[start] < arr[end] ? [arr[start], arr[end]] : [arr[end], arr[start]]
    }

    var mid = Math.floor((start + end) / 2);//中间相的下标  必须用下舍入
    var left = mergeSort(arr, start, mid) //左边的排序
    var right = mergeSort(arr, mid + 1, end)//右边的排序
    var resArr = [];//最终有序的数组

    while (left.length > 0 || right.length > 0) { //左边或右边还有内容
        left[0] < right[0] ? resArr.push(left.shift()) : resArr.push(right.shift())
        //当左边数组中没有元素,直接把右边数组里的数组拼接到最终结果的数组中resArr
        if (left.length == 0) {
            resArr = resArr.concat(right)
            break;
        } else if (right.length == 0) {//当右数组中没有元素,直接把左边数组里的数组拼接到最终结果的数组中resArr
            resArr = resArr.concat(left)
            break;
        }
    }
    return resArr
}               
2.3 快速/快排排序

**核心思想:**将一个数组一分为二,选一个元素作为标记,将比标记大的元素放到标记的右边,比标记小的元素放到标记的左边

算法步骤:

①找到中间项作为标记,将比标记大的元素放到标记的右边,比标记小的元素放到标记的左边

②对标记左边的部分重①直到排好顺序

③对标记右边的部分重①直到排好顺序

④左中右二部分排序之后再合并为一个又循的数组

代码:

scss 复制代码
function quickSort(arr) {
    // 递归的出口
    if (arr.length == 0) {
        return [] //数组里的元素为空的时候
    }

    var minIndex = Math.floor((arr.length - 1) / 2),//标记元素的下标
        midArr = arr.splice(minIndex, 1), //标记元素所在的数组
        left = [],
        right = []
    for (var i = 0; i < arr.length; i++) { //循环数组 
        if (arr[i] < midArr[0]) {
            left.push(arr[i])//比标记小的元素放到标记的左边
        } else {
            right.push(arr[i])//将比标记大的元素放到标记的右边,
        }
    }
    // 左中右二部分排序之后再合并为一个数组
    return quickSort(left).concat(midArr).concat(right)
}
2.4 插入排序

**核心思想:**通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上

算法步骤:

①从第一个元素开始,该元素可以认为已经被排序;

②取出下一个元素,在已经排序的元素序列中从后向前扫描;

③如果该元素(已排序)大于新元素,将该元素移到下一位置;

④重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;

⑤将新元素插入到该位置后;

⑥重复步骤2~5

代码:

css 复制代码
function inserSort(arr) {
    for (var i = 1; i < arr.length; i++) { //依次取出无序区域里每个元素每个元素
        for (var j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {//从或往前循环有序区域的元素,如果该元素比有序区域里的元素小就要插入在前
            var tmp = arr[j]
            arr[j] = arr[j + 1]
            arr[j + 1] = tmp
        }
    }
    return arr;
}
相关推荐
Never_Satisfied5 小时前
在JavaScript / HTML中,实现`<iframe>` 自适应高度
开发语言·javascript·html
koooo~7 小时前
Vue3中的依赖注入
前端·javascript·vue.js
细节控菜鸡10 小时前
【2025最新】ArcGIS for JS二维底图与三维地图的切换
javascript·arcgis
FuckPatience11 小时前
Vue 中‘$‘符号含义
前端·javascript·vue.js
光影少年18 小时前
vue打包优化方案都有哪些?
前端·javascript·vue.js
木易 士心1 天前
Ref 和 Reactive 响应式原理剖析与代码实现
前端·javascript·vue.js
uhakadotcom1 天前
execjs有哪些常用的api,如何逆向分析网站的加签机制
前端·javascript·面试
闲蛋小超人笑嘻嘻1 天前
find数组方法详解||Vue3 + uni-app + Wot Design(wd-picker)使用自定义插槽内容写一个下拉选择器
前端·javascript·uni-app
小牛itbull1 天前
初始化electron项目运行后报错 electron uninstall 解决方法
前端·javascript·electron
rggrgerj1 天前
Vue3 组件完全指南代码
前端·javascript·vue.js