前端笔记 JavaScript

前端笔记 JavaScript

rainbowYao Lv3

JavaScript简介

介绍

JavaScript是一种轻量级的脚本语言,是一种嵌入式(embedded)语言。

为什么学习JavaScript

操控浏览器的能力、广泛的使用领域、易学性

JavaScript与ECMAScript的关系

ECMAScript是JavaScript的规格,JavaScript是ECMAScript的实现,日常场合二者可互换


语法

语句

JavaScript程序的单位是行,一般情况下每一行是一个语句。语句以分号结尾,一个分号就表示一个语句结束

标识符

最常见的标识符就是变量名,标识符是由:字母、美元符号($)、下划线(_)、和数字组成,其中数字不能开头

JavaScript保留关键字

变量

变量重新赋值、变量提升

JavaScript引入到文件

嵌入到HTML文件中

1
2
3
4
5
<body>
<script>
var age = 20
</script>
</body>

引入本地独立JS文件

1
2
3
<body>
<script type="text/javascript" src="./aa.js"> </script>
</body>

引入网络来源文件

1
2
3
<body>
<script src="https://code.jquery.com/aa.js"> </script>
</body>

注释

单行注释://; 多行注释:/* */

JavaScript输出方式

1
2
3
4
5
6
7
8
//在浏览器中弹出一个对话框,然后把要输出的内容展示出来
alert("要输出的内容")

//直接输出到页面
document.write("要输出的内容")

//在控制台输出内容
console.log("要输出的内容")

数据类型

数值、字符串、布尔值、对象、undefined、null

typeof运算符可以返回number、string、boolean、object、undefined(null和undefined的区别是null是对象为空、undefined是数值为空)

运算符

算术运算符:+ - * / % ++ --

赋值运算符:= += -= *= /= %=

比较运算符:< > <= >= == ===(严格相等) != !==(严格不相等) ,严格比较:数值和类型都要求相同

布尔运算符:! && ||

语句

条件语句:if if……else switch 三目运算符,基本与C相同

循环语句:for while break continue,基本与C相同

字符串

\换行(类似于C宏定义)、length属性、charAtconcatsubstringsubstr(第二个参数不是结束位置,而是长度)、indexOf(第一次出现的位置,可以接受第二个参数,是开始检索的位置)、trim(去除字符串两端的空格,返回新字符串)、split

数组

[]表示数组、isArray弥补typeof的不足、push/popshift/unshift(相比于push、pop,这两个是操作数组的第一个元素)、join(以指定参数作为分隔符,将所有数组成员连接为一个字符串返回,默认是,)、concatreverse(颠倒数组元素,会改变原数组)、indexof

函数

function命令、函数名提升、函数参数、函数返回值

对象

对象的链式调用

Math对象

abs、max、min、floor、ceil、random

Date对象

now、getTime、getDate、getDay、getYear……


DOM

DOM是JavaScript操作网页的接口,全称为“文档对象模型”。它的作用是将网页转换为一个JavaScript对象,从而可以用脚本进行各样操作

节点

DOM的最小组成单位叫做节点,文档的树形结构(DOM树),就是由各种不同类型的节点组成

节点的类型有七种:

  • Document:整个文档树的顶层节点
  • DocumentType:doctype标签
  • Element:网页的各种HTML标签
  • Attribute:网页元素的属性(比如class="right"
  • Text:标签之间或标签包含的文本
  • Comment:注释
  • DocumentFragment:文档的片段

节点树

浏览器原生提供document节点,代表整个文档

Node.nodeType属性

document对象方法—获取元素

  • document.getElementsByTagName()方法搜索HTML标签名,返回符合条件的元素。它的返回值是一个类似数组对象(HTMLCollection实例)

  • document.getElementsByClassName()读取所有class名字符合指定条件的元素

  • document.getElementsByName()

  • document.getElementById()唯一标识

  • document.querySelector()接受一个CSS选择器为参数,返回匹配该选择器的元素节点,只能返回第一个匹配的

  • document.querySelectorAll()

document对象方法—创建元素

  • document.createElement():生成元素节点,并返回该节点
  • document.createTextNode():生成文本节点(Text实例),并返回该节点
  • appendChild:将内容或者子元素放到容器中
  • document.createAttribute():生成一个新的属性节点(Attr实例),并返回
  • setAttributeNode:将属性添加到节点中,可以有两个参数,第一个参数是属性,第二个参数是值

Element对象—属性

Element对象对应网页的HTML元素。每个HTML元素,在DOM树上都会转化成一个Element节点对象

  • Element.id
  • Element.className:操作class属性,每个class属性用空格分割
  • Element.classListadd()、remove()、contains()
  • Element.innerHTML:返回一个字符串,等同于该元素包含的所有HTML代码。可读写,用来设置某个节点的内同。他能改写所有元素节点的内容,包括<HTML>、<body>元素
  • Element.innerText:与innerHTML类似,不同的是无法识别元素,会直接渲染成字符串

Element获取元素位置

  • ELement.clientHeight、Element.clientWidth:获得元素高度、宽度包括padding部分,但不包括bordermargindocument.documentElement.clientHeight返回视口高度(即浏览器窗口高度),document.body.clientHeight返回网页的实际高度
  • Element.scrollHeight、Element.scrollWidth:元素总高度、宽度,包括padding,但不包括bordermargin,包括溢出的不可见内容,但基本和上面的一样
  • Element.scrollTop、Element.scrollLeft:垂直、水平滚动条滚动的像素数量
  • Element.offsetHeight、Element.offsetWidth:元素的CSS垂直高度、水平宽度,包括元素本身的高度、paddingborder,主要是多了个border
  • Element.offsetLeft、Element.offsetRight:到定位父级左边界、上边界的距离

CSS操作

HTML元素的style属性

操作CSS样式最简单的方法,就是使用网页元素节点的setAttribute方法直接操作网页的style属性

元素节点的style属性

直接操作style元素,如box.style.width = "300px";

cssText属性

利用元素的cssText属性,类似于第一种


事件处理程序

HTML事件

1
2
3
4
5
6
7
<button onclick="clickHandle()">按钮</button>

<script>
function clickHandle(){
alert('点击了按钮');
}
</script>

缺点是HTML和JavaScript没有分离

DOM0级事件

1
2
3
4
5
6
7
8
9
<button id="btn">按钮</button>

<script>
var btn = document.getElementById('btn');

btn.onclick = function(){
alert('hello');
}
</script>

优点是html和JavaScript是分离的,缺点是无法同时添加多个事件

DOM2级事件

1
2
3
4
5
6
7
8
9
10
11
12
13
<button id="btn">按钮</button>

<script>
var btn = document.getElementById('btn');

btn.addEventListener('click', function(){
alert('点击了按钮1');
});

btn.addEventListener('click', function(){
alert('点击了按钮2');
})
</script>

优点:时间不会被覆盖,缺点:写起来麻烦

事件类型之鼠标事件

鼠标事件指与鼠标相关的事件,具体有:

  • click:按下鼠标时触发
  • dblclick:在同一元素上双击鼠标时触发
  • mousedown:按下鼠标键时触发
  • mouseup:释放按下的鼠标键时触发
  • mousemove:当鼠标在节点的内部移动时触发。当鼠标持续移动时,该事件会连续出发
  • mouseenter:鼠标进入一个节点时触发,进入子节点不会触发
  • mouseleave:鼠标离开一个节点时触发,离开父节点不会触发
  • mouseover:鼠标进入一个节点时触发,进入子节点会再次触发
  • mouseout:鼠标离开一个节点时触发,离开父节点也会触发
  • wheel:滚动鼠标的滚轮时触发

注意DOM0事件前面通常加上on,如onclick

Event事件对象

事件发生之后,会产生一个事件对象,作为参数传递给监听函数

Event对象属性:

  • Event.target返回事件当前所在节点
  • Event.type返回一个字符串,表示当前事件类型

Event对象方法:

  • Event.preventDefault取消浏览器对当前事件的默认行为
  • Event.stopPropagation阻止事件在DOM中继续传播,防止再触发定义在别的节点上的监听函数,但是不包括在当前节点上其他的事件监听函数,即阻止事件冒泡

事件类型之键盘事件

  • keydown:按下键盘时触发
  • keypress:按下有值的键时触发,即按下Ctrl、Alt、Shift、Meta这样无值的键的时候不触发,对有值的键,按下时先触发keydown事件,再触发这个事件
  • keyup:松开键盘时触发该事件

keyCode代表每个按键的唯一标识

1
2
3
4
5
6
7
8
9
10
11
   <input type="text" id="input">

<script>
var input = document.getElementById('input');

input.onkeydown = function(e){
if(e.keyCode == 13){
alert('回车键');
}
}
</script>

事件类型之表单事件

  • input事件:当<input>、<select>、<textarea>的值发生变化时触发,对于复选框(input type=checkbox)或单选框(<input type=radio),用户改变选项时,也会触发这个事件
  • select事件:发生在<input>、<textarea>里面选中文本时触发
  • change事件:当<input>、<select>、<textarea>的值发生变化的时候触发,与input不同的是,不会连续触发,只是当全部修改完成时才会触发
  • reset事件、submit事件:这两个发生在表单对象<form>上,而不是发生在表单成员上。reset事件触发后表单重置,submit事件触发后表单数据向服务器提交,注意submit事件发生的对象是<form>表单元素,而不是<button元素,提交的是表单而不是按钮

事件代理(事件委托)

由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方法叫做事件的代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<ul>    
<li>1</li>
<li>2</li>
<p>hhh</p>
</ul>

<script>
var ul = document.querySelector('ul');

ul.addEventListener('click', function(e){
if(e.target.tagName == 'LI'){
alert(e.target.innerHTML);
}
})
</script>

定时器

setTimeout

setTimeout函数接受两个参数,第一个参数是将要推迟执行的函数或代码,第二个参数是延迟多少毫秒,返回定时器编号,可以用这个编号取消定时器

1
var timerId = setTimeout(func|code, delay);

温馨提示

如果回调函数是对象的方法,那么setTimeout使得方法内部的this关键字指向全局环境,而不是定义时所在的那个对象,解决方法是再定义一个that变量承载this

定时器也可以取消,使用clearTimeout(id)

setInterval

写法与setTimeout一致,区别在于这个函数指定某个任务每间隔多少秒执行一次,也就是无限次的定时执行,同时也可以用clearInterval取消

防抖(debounce)

效果:如果短时间内大量触发同一事件,只会执行一次函数

1
2
3
4
5
6
7
8
9
function debounce(fn, delay){
var timer = null;
return function(){
if(timer){
clearTimeout(timer);
}
timer = setTimeout(fn, delay);
}
}

节流(throttle)

效果:如果一直拖着滚动条进行滚动,也会在一定的时间间隔后执行

1
2
3
4
5
6
7
8
9
10
11
12
13
function throttle(fn, delay){
var flag = true;
return function(){
if(!flag){
return;
}
flag = false;
setTimeout(function(){
fn();
flag = true;
}, delay);
}
}

业务场景:

  • 搜索框input事件,例如要支持输入实时搜索可以使用节流方案,或者实现输入间隔大于某个值,就当作用户输入完成,然后开始搜索
  • 页面resize事件,常见于需要做页面适配的时候,需要根据最终呈现的页面情况进行dom渲染,这种一般使用防抖

ES6新特性

let和const命令

let用来声明变量,用法类似于var,但声明的变量只在let的代码块中有用

let块级作用域,适合用于for、let不存在变量提升、let不允许重复声明

const声明一个只读常量,一旦声明,常量的值就不能改变

const必须立刻初始化、作用域与let相同,只在声明的块级作用域内有效、也不提升、不允许重新赋值、不允许重复声明

对象解构赋值

解构可用于对象

1
let {name, age} = {name:"aa", age:20}

温馨提示

对象的属性没有次序,变量必须与属性同名,才能取到正确的值

对象的解构赋值,可以很方便的将现有对象的方法,赋值到某个变量

1
2
let {random, floor} = Math
let {log} = console

注意事项,如果要将一个已经声明的变量用于解构赋值,必须非常小心

1
2
3
4
5
let hello = "hello";
let { hello } = {hello:"hello"}; //报错

let hello = "hello";
({ hello } = {hello:"hello"}); //正确,但这样写也不好

字符串扩展

  • 字符串Unicode表示法

  • 字符串遍历器接口:for……of,类似于java中的加强for

  • 模板字符串:增强版的字符串,用反引号`` `标识。它可以当作普通的字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量

1
2
3
let url = "www.baidu.com"
let h1 = "<a href=' " + url + " '>baidu</a>"
let h2 = `<a href='${url}'>baidu</a>` //使用${}来提取变量内容

字符串新增方法

  • includes()、startsWith()、endsWith(),includes与indexof的区别在于可以返回布尔值,都支持第二个参数,即开始的位置
  • repeat()返回一个新的字符串,表示将原字符重复n
  • padStart()、padEnd():如果字符串不够指定长度,会在头部或尾部补全
  • trimStart(),trimEnd():与trim()一致,消除头部或尾部空格
  • at():接受一个整数作为参数,返回参数指定位置的字符,支持负索引(即倒数的位置)

数组扩展

  • 扩展运算符:...将一个数组用逗号分隔的参数序列,代替apply方法,也可以合并数组
  • Array.from():用于将类数组转为真正的数组

温馨提示

常见的类数组有:arguments(函数参数)、元素集合、类似数组的对象

  • Array.of():用于将一组值转化为数组

对象扩展

  • 属性名和属性值是相同的变量名称,可以省略,方法也可以简写,返回值也可以
  • 属性名表达式:用表达式作为对象的属性名,即把表达式放在方括号内
  • 对象也有扩展运算符:...,作用是展开数据

函数扩展

箭头函数:类似lambda表达式,常用于回调函数,箭头函数里面没有自己的this,而是引用外层的this

Set数据结构

类似于数组,成员唯一,含有size属性,add()、has()、clear()方法等

Promise对象

基本用法

promise对象是一个构造函数,用来生成promise实例

promise构造函数接受一个函数作为参数,该函数的两个参数分别为resolvereject,这两个函数由JavaScript引擎提供,不需要自己部署

promise实例产生后,可以用then方法分别指定resolved状态和rejected状态的回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script>
function loadImageAsync(url) {
const promise = new Promise(function(resolve, reject) {
const image = new Image();
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
})

return promise;
}

const promise = loadImageAsync('https://www.baidu.com/img/bd_logo1.png');
promise.then(function(image) {
document.body.appendChild(image);
}, function(error) {
console.log(error);
})
</script>

Async函数

async函数可以将异步操作变成同步操作,类似于java多线程同步控制,利用async修饰函数,利用await修饰需要等待的步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
function ajax(url) {
return new Promise((resolve, reject) => {
$.getJSON(url, function(data){
resolve(data);
}, function(err){
reject(err);
})
})
}

async function getInfo() {
var id = await ajax('...');
var info = await ajax('...' + id);
var result = await ajax('...' + info);
console.log(result);
}

getInfo();
</script>

Class

类似于java,构造方法:constructor(),不存在提升,静态方法,静态属性

Module语法

ES6模块通过export命令显式指定输出的代码,再通过import命令输入,导入时候的名字不能改,但可以通过as改名,也可以用*导入所有的内容,导入结果用as改名后封装成一个对象。export default可以使导入时无需同名,但一个文件里只能有一个

1
2
export var Hello = "hello" //hello.js
import { Hello } from "./hello.js" //index.js
  • 标题: 前端笔记 JavaScript
  • 作者: rainbowYao
  • 创建于 : 2024-07-01 21:27:53
  • 更新于 : 2024-09-18 09:20:42
  • 链接: https://redefine.ohevan.com/2024/07/01/前端笔记-JavaScript/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。