javascript初识
结构: html
表现: css
行为: javascript => JS 弱类型的语言
js初识
avaScript是一种专为与网页交互而设计的客户端脚本语言
JS组成:
ECMAScript 基础语法 ECMAScript5 => ES5 => ES6
BOM (Browser Object Model) 浏览器对象模型 操作浏览器的接口和方法 (页面跳转 前进后退 识别设备类型)
DOM (Document Object Model) 文档对象模型 提供了操作文档的接口和方法 => 获取元素 操作元素
JS的基本数据类型
JS数据类型 => 描述各种不同类型的数据
7种数据类型
string number boolean null undefined array object
字符串 数字 布尔值 空值 数组 对象
小技巧: 字符串=>黑色 数字/布尔值=>蓝色 null/undefined => 灰色
如何区分数据类型 ?
typeof 数据 => 数据类型(返回的是字符串)
null => "object"
undefined => "undefined"\
Math相关的方法
Math 数学(对象) 相关的方法(完成特定功能的工具)
Math.random() 随机生成一个 0-1的随机数 => [0,1)
var num = Math.random(); // 先随机一个0-1的随机数 再赋值给变量 num
console.log(num);
var num = Math.random() * 100; // [0,1) * 100 => [0,100)
console.log(num);
处理小数 ceil floor round
Math.ceil() 可以接收一个参数 对其向上取整 返回 => 有小数位 就进 1
var num1 = Math.ceil(num);
console.log(num1);
Math.floor() 可以接收一个参数 对其向下取整后返回 => 去掉小数位
var num2 = Math.floor(num);
console.log(num2);
Math.round() 可以接收一个参数 对其四舍五入后返回 => 四舍五入
var num3 = Math.round(num);
console.log(num3);
Math.min() 可以接收一个参数或多个参数(逗号分隔),返回最小值
var min = Math.min(2,8,4,6,5,7,9,3,1);
console.log(min);
Math.max() 可以接收一个参数或多个参数(逗号分隔),返回最大值
var max = Math.max(2,8,4,6,5,7,9,3,1);
console.log(max);
Math.abs() 可以接收一个参数 返回该数的绝对值
var a = Math.abs(10);
var a = Math.abs(-10);
console.log(a);
Math.pow(m,n) 可以接收两个参数 => m的n次方
var b = Math.pow(2,10);
console.log(b);
Math.PI 返回π
console.log(Math.PI);
强制类型转换
string number boolean null undefined
Number() 传入一个参数,将其转化为数字并返回 (将其他类型转化为数字)
var result = Number("100");
console.log(result);
console.log(Number("100")); // 100
console.log(Number("100a")); // NaN
console.log(Number(100)); // 100
console.log(Number(true)); // 1
console.log(Number(false)); // 0
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN */
String() 传入一个参数,将其转化为字符串并返回 (将其他类型转化为字符串)
console.log(String("100")); // "100"
console.log(String("100a")); // "100a"
console.log(String(100)); // "100"
console.log(String(true)); // "true"
console.log(String(false)); // "false"
console.log(String(null)); // "null"
console.log(String(undefined)); // "undefined"
强制类型转换_Boolean
string number boolean null undefined
Boolean() 传入一个参数,将其转化为布尔值并返回 (将其他类型转化为布尔值)
"" 0 NaN null undefined => 转化为布尔值为false
console.log(Boolean("100")); // true
console.log(Boolean("100a")); // true
console.log(Boolean("a")); // true
console.log(Boolean(" ")); // 空格字符串 true
console.log(Boolean("")); // 空字符串 false
console.log(Boolean(100)); // true
console.log(Boolean(-100)); // true
console.log(Boolean(0.5)); // true
console.log(Boolean(0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean(Infinity)); // true
console.log(Boolean(true)); // true
console.log(Boolean(false)); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
parseInt 和 parseFloat
parseInt() parseFloat() 主要用来处理数字和字符串 ,其他类型 => NaN
parseInt() 把其他类型转化为整型(整数) 1.去单位 2.向下取整
规律: 找到第一个非数字之前的数 将其转为整数
parseFloat() 把其他类型转化为浮点的型(可以保留小数)
规律: 找到第一个非数字之前的数 保留小数
var width = "200px"; // => 200
var width = "2a00px"; // => 2
var width = "a200px"; // => NaN
var width = 200.55; // => 200
var result = parseInt(width);
console.log(result);
var width = "200px"; // => 200
var width = "200.55px"; // => 200.55
var width = "2a00.55px"; // => 2
var width = 200.55; // => 200.55
var result = parseFloat(width);
console.log(result);
a++ 和 ++a的区别
a++ ++a 就结果而言 本身都自增了
如果在自增过程中出现了 其他操作
a++ 先赋值 再自增
++a 先自增 再赋值
var a = 10;
a++;
console.log(a);
var a = 10;
++a;
console.log(a);
如果在自增过程中出现了 其他操作
a++ 先赋值 再自增
++a 先自增 再赋值
var a = 10;
var n = a++; // var n = a; a = a + 1; 先赋值 再自增
console.log(n); // 10
console.log(a); // 11
var a = 10;
var n = ++a; // a = a + 1; var n = a; 先自增 再赋值
console.log(n); // 11
console.log(a);// 11
选择结构
选择结构 根据不同的情况,执行对应代码
选择结构 if
单分支
双分支
多分支
单分支 满足条件才 执行 否则不做任何操作
if(表达式){
执行语句;
}
如果表达式成立(true),则执行{}中的语句(执行语句),否则不做任何操作,继续执行选择结构之后的代码
双分支 两个选择 => 必须走一个
if(表达式){
执行语句 1;
}else{
执行语句 2;
}
求解表达式 如果表达式成立(true),则执行{}中的执行语句1 ,否则 执行else 对应的{}中的语句2
判断完毕 => 继续执行位于 选择结构之后的语句
多分支
if(表达式1){
执行语句 1;
}else if(表达式2){
执行语句 2;
}else if(表达式3){
执行语句 3;
}else{
执行语句 4;
}
关系运算符的隐式类型转换
ASCII => GB2312 GBK => unicode => UTF-8
关系运算符的隐式类型转换 > >= < <= == !=
1. 字符串,布尔值 在和数字比较时 会先隐式的转化为数字 再比较
2. 字符串 和 字符串 比较时, 按照顺序 比较字符的ASCII码 大小
3. null和undefined 遇到 > >= < <= 会先转数字再比较
遇到 == != 不转化 直接比较 (没有可比性)
4. null和undefined 在数值上是相等的(==)
5. NaN和任何值都不相等
++ --的隐式类型转换
++ – 的隐式类型转换
其他类型的数据(string boolean null undefined) 遇到 ++ – 会先隐式的转化为数字 再自增/自减
var a = 10;
var a = "10"; // "10" => 10 a++ => 11
var a = "10a"; // "10a" => NaN a++ =>NaN
var a = ""; // "" => 0 a++ => 1
var a = true; // true => 1 a++ => 2
var a = false; // false => 0 a++ => 1
var a = null; // null => 0 a++ => 1
var a = undefined; // undefined => NaN a++ =>NaN
运算符的优先级
算术运算符 * / % 大于 + -
关系运算符 > >= < <= 大于 == != === !==
逻辑运算符 ! && ||
赋值运算符 ++ -- 大于 = += -= *= /=
() . [] > ! ++ -- > 算术运算符 > 关系运算符 > 逻辑运算符 (!比较特殊) > 赋值运算符 (++ -- 比较特殊)
选择结构之switch
switch 典型的多分支
switch(week){
case 常量1: 执行语句1; break;
case 常量2: 执行语句2; break;
case 常量3: 执行语句3; break;
case 常量4: 执行语句4; break;
case 常量5: 执行语句5; break;
default:
执行语句5;
break;
}
switch中的表达式一般是一个变量/常量, 针对该变量可能出现的情况 进行列举;
switch如何执行?
switch中的表达式 和 case中的常量 依次进行 全等(===) 比较 ,如果全等则执行对应的语句, 语句执行完毕 遇到break 会跳出switch结构; 如果不全等,继续向下比较, 全都不满足则执行default之后的语句
区别:
switch 更适合做数值判断 列举变量可能出现的情况
if 更适合做范围判断, 多条件
选择结构之switch穿透
switch 典型的多分支
switch(week){
case 常量1: 执行语句1; break;
case 常量2: 执行语句2; break;
case 常量3: 执行语句3; break;
case 常量4: 执行语句4; break;
case 常量5: 执行语句5; break;
default:
执行语句5;
break;
}
switch中的表达式一般是一个变量/常量, 针对该变量可能出现的情况 进行列举;
switch如何执行?
switch中的表达式 和 case中的常量 依次进行 全等(===) 比较 ,如果全等则执行对应的语句, 语句执行完毕 遇到break 会跳出switch结构; 如果不全等,继续向下比较, 全都不满足则执行default之后的语句
break的作用是跳出当前switch结构,如果没有break 则会继续执行后续分支的语句,而不进行判断
区别:
switch 更适合做数值判断 列举变量可能出现的情况
if 更适合做范围判断, 多条件
选择结构之switch穿透应用
switch 典型的多分支
switch(week){
case 常量1: 执行语句1; break;
case 常量2: 执行语句2; break;
case 常量3: 执行语句3; break;
case 常量4: 执行语句4; break;
case 常量5: 执行语句5; break;
default:
执行语句5;
break;
}
switch中的表达式一般是一个变量/常量, 针对该变量可能出现的情况 进行列举;
switch如何执行?
switch中的表达式 和 case中的常量 依次进行 全等(===) 比较 ,如果全等则执行对应的语句, 语句执行完毕 遇到break 会跳出switch结构; 如果不全等,继续向下比较, 全都不满足则执行default之后的语句
switch 穿透
break的作用是跳出当前switch结构,如果没有break 则会继续执行后续分支的语句,而不进行判断
利用switch穿透 可以按照数值 进行分门别类
区别:
switch 更适合做数值判断 列举变量可能出现的情况
if 更适合做范围判断, 多条件
三目运算符
语法:
表达式1 ? 表达式2 : 表达式3;
首先求解表达式1 如果表达式1成立,则求解表达式2 否则求解表达式3
while循环
while语法结构
while (表达式) {
执行语句;
}
首先求解表达式 ,如果表达式成立(满足条件),则执行{}中循环语句; 语句执行完毕,再次求解表达式,如果依旧成立,则继续循环,否则会跳出循环 执行循环之后的语句
do while循环
while 先判断 再执行 => 理智型
do…while 无论条件成立与否 先执行一次 再判断 => 冲动型
总结:
对比while 和 do...while
一般情况下 更倾向于使用 while
只有在 while处理循环逻辑 比较别扭的时候使用do...while
for循环
for语法结构
for(i=0;i<length;i++){
执行语句;
}
循环中的关键词
continue; 跳过本次进入下一次 (只能在循环语句中使用,使本次循环结束,即跳过循环体中下面尚未执行的语句,接着进行下次)
注意:
(1) 位于continute之后的语句不执行
(2) 对于 while 和 do-while 循环,continue 语句执行之后的动作是条件判断(求解表达式);对于 for 循环,随后的动作是变量更新(自增/自减)。
break 循环的关键词
break用在循环中表示跳出当前循环
注意:
(1) 位于break之后的循环语句不执行
(2) 如果有多层循环嵌套,break只跳一层(当前循环)
函数的封装流程及函数调用
函数就是把完成特定功能的一段代码抽象出来,使之成为程序中的一个独立实体,起个名字(函数名)。可以在同一个程序或其他程序中多次重复使用(通过函数名调用)。
函数封装的流程
(1) 先将完成特定功能的代码写出来
(2) 把完成特定功能的代码 放到函数中 起一个名字
(3) 确定函数的返回值 => 返回值由用户自行决定,不设置 默认就是undefined
(4) 调用函数 => 函数名()
关于函数的调用
(1) 函数在没有调用之前,都是以文本的形参存储在浏览器的内存当中 (函数名可以理解为变量名),调用时才会执行
(2) 每次调用函数 都会执行函数中的上下文
(3) 函数遇到return就结束了 后续的代码不在执行
函数的嵌套
函数的嵌套是指在一个函数中 可以 嵌套调用 另外一个或多个函数
注意:
函数嵌套调用时 => 只有当内层函数执行完毕,外层函数才会继续向后执行 (代码执行流程)
如果向将内层函数的返回值 返回出外层函数 => 外层函数也要return该值 (关于返回值)
函数的递归
递归
函数在执行过程中 调用了自己;
注意: 递归一定要有跳出条件
死递归 => 类似死循环
function fn(){
console.log("这是fn函数");
fn();
}
fn();
尾递归 => 在结尾得到最终结果 在依次向回传递
function fn(i,sum){ // fn(2,12)
console.log(i,sum);
sum += i;
if(i == 1){
return sum;
}
return fn(i-1,sum); // fn(1,14)
}
依赖性递归 => 每个函数的结果 依赖于 前一个或多个的结果
function fn(n){
if(n == 1) {
return 1;
}
return n + fn(n-1);
}
JS预编译
JS中的代码从加载到执行经历了哪些流程?
1. 语法解析
发生在代码执行之前 排查当前script中是否有语法错误 => 有错误就报错,代码不执行
2. 预编译 => 发生在代码执行之前,代码执行之前的准备工作
(1) 全局作用域 => 全局作用域中代码执行之前的准备工作
a. 变量提升 把变量声明 提升到当前script的最前面 (注意:不通过关键词声明的变量 => 全局变量 没有变量提升)
b. 确定函数体 把命名函数整个函数声明 提升到当前script的最前面
(2) 函数作用域 函数中代码执行之前的准备工作
a. 变量提升 把变量声明 提升到当前函数作用域的最前面
b. 确定函数体 把命名函数函数 提升到当前函数作用域的最前面
c. 把实际参数赋值给形式参数
3. 解释执行 代码从上向下依次执行
JS函数的创建方式
一. 命名函数 (声明式)
function add(a,b){
return a + b;
}
console.log(add);
add()
默认情况下 js语法在解析函数时 是以命名函数方式解读的 => 不能直接创建匿名函数 放在作用域中 (匿名函数一般情况下 不能单独存在)
function(a,b){
return a + b;
}
二 .匿名函数
1. 把匿名函数存储到 变量 数组 对象 (赋值式)
var fn = function(a,b){
return a + b;
}
console.log(fn);
var result = fn(1,2)
console.log(result);
var arr = [1,2,3,function(){}]
var obj = {
name:"张三",
age:18,
say:function(){
console.log("hello");
}
}
btn.onclick = function(){
alert(1111);
}
2. 匿名函数的自调用/自执行
(function(a,b){
return a + b;
})
;+function(a,b){
return a + b;
}
;-function(a,b){
return a + b;
}
;!function(a,b){
return a + b;
}
数组的创建方式
数组的创建方式
1. 字面量/直接量 创建 => 快捷创建
var arr = [2,8,4,6,5,9,7,3,1];
var arr = []; //空数组
console.log(arr);
2. 构造函数(Array)创建
var arr = new Array(2,8,4,6,5,9,7,3,1); // new Array() 调用构造函数
var arr = new Array(); //[]
console.log(arr);
数组的特性:
1. 有length属性,表长度(数组中元素的个数)
2. 对应下标取值和赋值 下标的最大值 = length - 1
3. 可以被循环遍历
数组的拓展方法
官方封装的操作数组的方法
学习数组的拓展方法需要注意哪些问题?
1. 记住方法的作用
2. 方法的返回值
3. 是否影响原数组 => (1. 有些方法 直接操作原数组 2. 有些方法 根据原数组得到新数组)
数组的增删改查
push() 在数组的尾部添加一个或多个元素
返回值: 新增元素后数组的长度
是否影响原数组: 影响
var arr = ["a","b","c"];
var result = arr.push(100);
var result = arr.push(100,200,300);
console.log(result);
console.log(arr);
unshift() 在数组的头部添加一个或多个元素
返回值: 新增元素后数组的长度
是否影响原数组: 影响
var arr = ["a","b","c"];
var result = arr.unshift(100);
var result = arr.unshift(100,200,300);
console.log(result);
console.log(arr);
pop() 在数组的尾部删除一个元素
返回值: 被删除的元素
是否影响原数组: 影响
var arr = ["a","b","c","d"];
var result = arr.pop();
console.log(result); // "d"
console.log(arr); // ["a","b","c"]
var result = arr.pop();
console.log(result); // "c"
console.log(arr); // ["a","b"]
shift() 在数组的头部删除一个元素
返回值: 被删除的元素
是否影响原数组: 影响
var arr = ["a","b","c","d"];
var result = arr.shift();
console.log(result);
console.log(arr);
splice() 任意位置增删改
删除
splice(startIndex,n) 从下标为startIndex的位置开始 删除n个元素
返回值: 被删除的元素形成的新数组
是否影响原数组 : 是
var arr = [2,8,4,6,5,7,9,3,1];
var result = arr.splice(2,4);
console.log(result);
console.log(arr);
新增
splice(startIndex,0,arg1,arg2...argN) 从下标为startIndex的位置开始 删除0个元素,在新增一个或多个元素(从第三参数开始 都是新增的元素)
返回值: 被删除的元素形成的新数组 => 没有删 []
是否影响原数组 : 是
var arr = [2,8,4,6,5,7,9,3,1];
var result = arr.splice(2,0,"a","b","c");
console.log(result);
console.log(arr);
修改
splice(startIndex,n,arg1,arg2...argN) 从下标为startIndex的位置开始 删除n个元素,在新增一个或多个元素(从第三参数开始 都是新增的元素)
返回值: 被删除的元素形成的新数组
是否影响原数组 : 是
var arr = [2,8,4,6,5,7,9,3,1];
var result = arr.splice(2,3,"a","b","c");
console.log(result);
console.log(arr);
查找 判断数组中是否存在某个元素? => 模拟封装
var arr = [2,8,4,6,5,7,4,9,3,1];
console.log(arr);
includes() 判断数组中是否存在某个元素 (ES6 新增)
返回值: 存在:true 不存在:false
是否影响原数组: 不影响
var result = arr.includes(1);
var result = arr.includes("1");
console.log(result);
console.log(arr);
indexOf() 返回某个元素在数组中第一次出现的位置
返回值: 有该元素 就返回下标,否则返回-1
是否影响原数组: 不影响
var result = arr.indexOf(4); // 2
var result = arr.indexOf("4"); // -1
console.log(result);
indexOf() 也可以用于判断是否存在 某个元素
存在 index >= 0 index != -1
不存在 index == -1
reverse() 数组的翻转 / 反转
返回值: 翻转后的原数组
是否影响原数组: 影响
var arr = ["a","b","c","d","e"]; // => ["e","d","c","b","a"]
var result = arr.reverse();
console.log(result);
console.log(arr);
slice(startIndex,endIndex) 数组的裁切 [startIndex,endIndex)
startIndex 起始下标(默认值:0)
endIndex 终止下标(默认值:数组的长度 length)
返回值 裁切后的新数组
是否影响原数:不影响
常用于:
(1) 前端分页
(2) 数组的复制 得到一个与原数组元素相同的新数组
var arr = [1,2,3,4,5,6,7,8,9];
var brr = [];
for(var i=0;i<3;i++){
var item = arr[i];
brr.push(item);
}
var result = arr.slice(0,3);
var result = arr.slice(3,6);
var result = arr.slice(6,9);
console.log(result);
console.log(arr);
var brr = [];
for(var i=0;i<arr.length;i++){
var item = arr[i];
brr.push(item);
}
得到一个与原数组元素相同的新数组
var result = arr.slice();
console.log(result);
console.log(arr);
sort() 数组的排序
字符排序(默认) 按照ascii 码表的顺序排序
返回值: 排序后的原数组
是否影响原数组: 影响
字符排序
var list = [52, 9, 28, "A", 3, 71, "a", 94, 1000000000, 62, 46, 5];
var result = list.sort();
console.log(result);
console.log(list);
纯数字排序
sort() 传入一个函数,函数中有两个形式参数(a,b 参与比较的两个元素),函数要求返回一个算术表达式用于规定排序的方式
var list = [52, 9, 28, 3, 71, 94 ,62, 46, 5];
list.sort(function(a,b){
// console.log(a,b);
// return a - b; // a - b > 0 => a > b 如果 前一个数 大于 后一个数 交换两个数的位置 (从小到大)
return b - a; // b - a > 0 => a < b 如果 前一个数 小于 后一个数 交换两个数的位置 (从大到小)
});
console.log(list);
concat() 将多个数组,元素拼接形成一个新数组
如果是数组,则遍历数组 将每个元素放到新数组中
如果不是数组,则直接放到新数组中
返回值:拼接形成的新数组
是否影响原数组: 不影响
var arr = [1,2,3];
var brr = [4,5,6];
var crr = [7,8,9];
var result = arr.concat(brr,crr);
var result = brr.concat(arr,crr);
console.log(result);
console.log(arr,brr,crr);
[]
var result = arr.concat("a",brr,"b",crr,"c");
console.log(result);
console.log(arr,brr,crr);
得到一个与原数组中 元素相同的新数组
var arr = [1,2,3];
var list = arr.concat();
console.log(list);
console.log(arr);
join(char) 用特定的字符将数组拼接形成字符串 (char默认",")
返回值:拼接形成的字符串
是否影响原数组: 不影响
var list = ["a","b","c","d"]; // "abcd"
var str = "";
for(var i = 0; i< list.length;i++){
var item = list[i]; // 数组中的每一个元素
str += item;
}
console.log(str);
var list = ["a","b","c","d"]; // "a-b-c-d"
var str = "";
for(var i = 0; i< list.length;i++){
var item = list[i]; // 数组中的每一个元素
if(i!= list.length-1){
str += item + "-";
}else{
str += item ;
}
}
console.log(str);
var list = ["a","b","c","d"];
var result = list.join("-");
console.log(result);
var result = list.join("+");
console.log(result);
var result = list.join("*");
console.log(result);
var result = list.join("");
console.log(result);
var result = list.join();
console.log(result);
for in和for of
string number boolean null undefined => 值类型 (普通数据类型)
array object => 引用数据类型(特殊数据类型)
var arr = [4,8,2,6,5,7,9,3,1];
var arr = new Array(4,8,2,6,5,7,9,3,1);
数组的特性
length
下标取值和赋值 下标的最大值 = length - 1
可以被循环遍历
0 length-1
var arr = [4,8,2,6,5,,,,,,,,,,,7,9,3,1];
console.log(arr);
for(var i = 0;i<arr.length;i++){
console.log(i,arr[i]);
}
for...in 遍历数组 返回数组的下标
注意:
1. 通过for...in循环 遍历得到的下标index 是字符串类型
2. for...in循环 遍历数组时 会跳过空值(空余出来的)
var arr = [4,8,2,6,5,,,,,,,,,,,7,9,3,1];
console.log(arr);
for(var index in arr){
console.log(index,typeof index,arr[index]);
}
for...of 遍历数组 返回数组的值
var arr = [4,8,2,6,5,7,9,3,1];
console.log(arr);
for(var val of arr){
console.log(val,arr.indexOf(val));
}
对象
数组可以存储 多条数据 但是对数据的描述不够清晰
var arr = [“张三”, 55, 66, 77];
console.log(arr,typeof arr);
对象: 对一个或一类事物 特征和行为的描述
注意
(1) 对象是以键值(key:value)对形式存在的
(2) 数组也是一个特殊的对象 (键名是数字)
(3) 键名都是字符串 引号可以省略
如何创建对象? 键名的引号可以省略
1. 字面量创建
var zhang = {
键名(属性名 字符串) : 键值(属性值 任意类型)
"name":"张三",
"chinese": 55,
"math":66,
"english":77,
"hobby":["唱歌","跳舞"]
}
var zhang = {}; // {} 空对象
var zhang = {
// 键名(属性名 字符串) : 键值(属性值 任意类型)
name:"张三",
chinese: 55,
math:66,
english:77,
hobby:["唱歌","跳舞"]
}
console.log(zhang);
2. 构造函数创建(Object)
var zhang = new Object({}) // {}
var zhang = new Object({
name:"张三",
chinese: 55,
math:66,
english:77,
hobby:["唱歌","跳舞"]
});
console.log(zhang);
对象的特性
数组可以存储 多条数据 但是对数据的描述不够清晰
var arr = [“张三”, 55, 66, 77];
console.log(arr,typeof arr);
console.log(arr.length,arr[0]);
对象: 对一个或一类事物 特征和行为的描述
注意
(1) 对象是以键值(key:value)对形式存在的
(2) 数组也是一个特殊的对象 (键名是数字)
(3) 键名都是字符串 引号可以省略
对象的特性:
(1) 对应键名取值和赋值 (排名不分先后)
a. 点语法 对象.属性名 => 快捷取值
b. 中括号 对象["属性名"] => 中括号中要求放字符串/变量 => 对象遍历 函数封装对象取值
对象取值取不到(取一个不存在的属性名) 则返回undefined
对象赋值一个不存在的属性 则新增该属性到对象中
(2) 可以被循环遍历 for...in
数组的浅复制和深复制
浅复制(拷贝) 两个数据引用同一片内存空间 只要一个改变 另一个也会收到影响(===)
var arr = [1,2,3];
var brr = arr; // brr = [1,2,3]
brr.push(4); // brr = [1,2,3,4]
console.log(arr,brr,arr === brr);
深复制(拷贝) 得到一个和原数组元素相同的新数组
var arr = [1,2,3];
(1) 创建新数组 遍历原数组 将每个元素放到新数组中
var brr = [];
for(var i = 0;i<arr.length;i++){
var item = arr[i]; //1 2 3
brr.push(item);
}
console.log(arr,brr,arr === brr);
(2) 借助数组的拓展方法 arr.slice() arr.concat();
var arr = [1,2,3];
var brr = arr.slice();
var brr = arr.concat();
console.log(arr,brr,arr === brr);
如何判断一个数据是否是数组
var arr = [2,8,4,6]; // new Array() => 通过构造函数创建的对象 => 实例化对象
var obj = {a:1,b:2}; // new Object()
console.log(typeof arr);// 'object'
console.log(typeof obj);// 'object'
instanceof 判断某个数据 是否是由 某个构造函数创建的 (不完全 存在缺陷)
console.log(arr instanceof Array); // arr是否是由构造函数Array创建的 (是否是Array的实例化对象)
console.log(obj instanceof Object); // obj是否是由构造函数Object创建的 (是否是Object的实例化对象)
Array.isArray() 构造函数Array本身的方法 => 传入一个数据判断是否是数组 是:true 不是:false
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false
console.log(Array.isArray(1)); // false
console.log(Array.isArray("100"));// false
console.log(Array.isArray(true)); // false
字符串
string number boolean null undefined array object
typeof
字符串 获取和设置一段文本
字符串的创建方式
1. 字面量创建
var str = "hello";
console.log(str,typeof str); // "hello" "string"
2. 构造函数创建
var str = new String("hello");
console.log(str,typeof str); // {"hello"} 'object'
console.log(str+1);
var num = 1;
console.log(num,typeof num);
var num = new Number(1);
console.log(num,typeof num,num+1);
var bool = true;
console.log(bool,typeof bool);
var bool = new Boolean(true);
console.log(bool,typeof bool,bool+true);
字符串的特性
1.有length属性,表长度,在字符串中表示字符的个数
2.可以通过下标取值,但是不能通过下标赋值(官方决定的 =>字符串的拓展方法都不会影响原字符串,操作字符串都会返回新字符串) 下标的在最大值 = length - 1
3. 可以被循环 遍历
字符串的拓展方法
charAt(index) 传入一个下标 返回对应下标的字符 查不到返回""
var str = "hello world";
var char = str.charAt(6);
console.log(char,str[6]);
var char = str.charAt(100);
console.log(char,str[100]); // ""
charCodeAt() 传入一个下标 返回对应下标的字符的编码(ascii) => 判断字符编码范围
var code = str.charCodeAt(6) // w => 119
var code = str.charCodeAt(4) // o => 111
console.log(code);
code 48-57 =>数字
code 65-90 =>大写
code 97-122 =>小写
!!! 构造函数String的方法
String.fromCharCode() 构造函数String的方法 => 传一个或多个字符编码 => 返回对应字符/字符串
var char = String.fromCharCode(119);
console.log(char);
var str1 = String.fromCharCode(119,111);
var str1 = String.fromCharCode(72,101,108,108,111);
console.log(str1);
indexOf() 返回某个或某段字符 在字符串中第一次出现的位置 存在返回下标 不存在-1
var str = "good good study , day day up";
var index = str.indexOf("d"); // 3
var index = str.indexOf("day"); // 18
var index = str.indexOf("day123"); // -1
console.log(index);
indexOf(searchChar,startIndex) indexOf()可以接收第二参数作为查询的起始下标(默认0)
var index = str.indexOf("d",4); // 8
var index = str.indexOf("day",19); // 22
console.log(index);
lastIndexOf() 返回某个或某段字符 在字符串中最后一次出现的位置 存在返回下标 不存在-1
倒着遍历查询 length-1 => 0
var str = "good good study , day day up";
var index = str.lastIndexOf("d"); // 22
var index = str.lastIndexOf("d",21); //18
console.log(index);
includes() 判断字符串中是否存在 某个或某段字符 (ES6)
var str = "good good study , day day up";
console.log(str.includes("d"));
console.log(str.includes("day"));
console.log(str.includes("day123"));
concat() 字符串拼接(多个字符 字符串拼接形成新的字符串)
var str1 = "hello";
var str2 = "world";
var str = str1.concat(" ",str2);
var str = str1 + " " + str2;
console.log(str);
字符串裁切
slice(startIndex,endIndex) 字符串裁切
var str = "good good study , day day up";
var result = str.slice(10,15); // "study"
var result = str.slice(22,25); // "day"
slice() 可以接收负值 => 字符串的长度 + 负值
var result = str.slice(-6,-3); // "day" -6=>28-6 -3=> 28-3
console.log(result);
substring(startIndex,endIndex) 用法同slice 参数不能接收负值
var str = "good good study , day day up";
var result = str.substring(10,15); // "study"
var result = str.substring(22,25); // "day"
console.log(result);
substr(startIndex,length) 自下标为startIndex的位置开始 裁切对应长度的字符串
var str = "good good study , day day up";
var result = str.substr(10,5); // "study"
var result = str.substr(22,3); // "day"
console.log(result);
innerText和innerHTML
非表单元素的取值和赋值
innerHTML 获取和设置元素内的html结构(纯文本也会获取和设置文本)
innerText 获取和设置元素内的文本结构(如果设置 html结构会原样输出)
isNaN() 传入一个参数 判断是否是非数字 非数字返回true 数字返回false
(也可以用于判断是否是数字 数字返回false)
如果传入的参数是number类型 直接判断
如果传入的参数是number以外的其他数据类型 先隐式转化为数字 在判断
console.log(isNaN(NaN));
console.log(isNaN(100));
console.log(isNaN("100")); // "100" => 100 false
console.log(isNaN("")); // "" => 0 false
console.log(isNaN(true)); // true => 1 false
console.log(isNaN(null)); // null => 0 false
console.log(isNaN("100a")); // "100a" => NaN true
console.log(isNaN(undefined)); // undefined => NaN true
逻辑运算符拓展
如果且和或两边 不是布尔值 => 并不会转化为布尔值 而是遵从短路运算的规则(规律:看成布尔值)
&& 同真为真 遇假为假 => 找假的,找到后面就不用看了
console.log(true&&true);
console.log(true&&false);
console.log(1 && 2); // 2
console.log(1 && 0); // 0
console.log(0 && 2); // 0
console.log(0 && ""); // 0
console.log(1 && 3 && 2); // 2
console.log(1 && null && 2); // null
同假为假 遇真为真 => 找真的 ,找到后面就不用看了
console.log(true||true);
console.log(false||true);
console.log(1 || 2); //1
console.log(0 || 2); //2 => 变相的用于判断有没有值?
console.log("" || 2); //2 => 变相的用于判断有没有值?
console.log(undefined || 2); //2 => 变相的用于判断有没有值?
字符串的拓展方法
toUpperCase() 字母转大写 返回转化后的新字符串
toLowerCase() 字母转小写 返回转化后的新字符串
var str = "Hello World";
var upStr = str.toUpperCase();
console.log(upStr);
var lowStr = str.toLowerCase();
console.log(lowStr);
trim() 去重首尾空格 => 返回新的字符串
trimLeft() | trimStart() 去重头部空格 => 返回新的字符串
trimRight() | trimEnd() 去重头部空格 => 返回新的字符串
search match replace split() 普通用法 + 配合正则表达式使用
search() 查找
普通用法 返回某个或某段字符 在字符串中第一次出现的位置 存在:返回下标 (同indexOf())
var str = "good good study , day day up";
var index = str.search("d"); //3
var index = str.search("day"); // 18
var index = str.search("day123"); // -1
console.log(index);
配合正则表达式使用 => 返回符合规则的某个或某段字符 在字符串中第一次出现的位置
var str = "good good study , Day123 dAy up";
var reg = /day/; // 不区分大小写 -1
var reg = /day/i; // 忽略大小写 D|a A|a Y|y DAY DaY DAy dAY daY dAy Day day
var reg = /day/ig; // g全局匹配(匹配整个字符串中所有的 不加g默认只匹配一个) 但是search方法g修饰符没有效果
var index = str.search(reg)
console.log(index);*/
match() 匹配
普通用法 将匹配的内容(某个或某段字符串)放到数组中返回 (默认只匹配一个) 存在:返回数组 不存在:null
var str = "good good study , day day up";
var arr = str.match("day"); // ["day",index:18]
var arr = str.match("Day");
console.log(arr);
配合正则表达式使用 => 将符合规则的某个或某段字符串 放到数组中(默认只匹配一个 配合修饰符g 可以匹配整个字符串)
var str = "good good study , Day dAy up";
var reg = /day/; // day
var reg = /day/i; // 忽略大小写 D|a A|a Y|y => DAY DaY DAy dAY daY dAy Day day
var reg = /day/ig; // 忽略大小写 全局匹配
var arr = str.match(reg);
console.log(arr);
replace(oldStr,newStr) 替换
普通用法 将字符串中的某个或某段字符 替换为 另一个字符串 (用新的字符串替换原本的字符串) =>新字符串 (默认只匹配一个)
var str = "good good study , day day up";
var newStr = str.replace("day","money");
console.log(newStr);
配合正则表达式使用 => 将符合规则的某个或某段字符 替换为 另一个字符串 (默认只替换一个 配合修饰符g 可以替换整个字符串)
var str = "good good study , Day dAy up";
var reg = /day/; // day
var reg = /day/i; // 忽略大小写
var reg = /day/ig; // 忽略大小写
var newStr = str.replace(reg,"money")
console.log(newStr);
去除所有空格
var str = " good good study , Day dAy up ";
var reg = / /g;
var newStr = str.replace(reg,"");
console.log(newStr);
split()
普通用法 用特定的字符将字符串拆分为数组
var str = "a-b-c-d";
var list = str.split("-");
var list = str.split(""); // 拆分得到每一个字符
console.log(list);
配合正则表达式使用 => 用符合规则的某个或某段字符 将字符串拆分为数组
var str = "a-b-c-d";
var reg = /-/g; //用-拆分
var list = str.split(reg); // 拆分得到每一个字符
console.log(list);
join()
var list = ["a","b","c","d"];
var str = list.join("-");
console.log(str); // "a-b-c-d"
正则表达式
正则表达式(Regular Expression)
是字符串的一种匹配模式(可以用于表单验证 字符串匹配) => 简单的来说 就是用既定的规则来匹配字符串
用户名
由数字 大小写字母 _ $ 组成 , 6-12位,且不能以数字开头 /^[a-zA-Z_][0-9a-zA-Z_]{5,11}$/ig
密码
由数字 大小写字母 _ 组成 6-12位
邮箱
*********@qq.com
正则表达式的组成
(1) 规则 /day/
(2) 修饰符 i(忽略大小写 ignore case) g(全局匹配 global)
正则表达式的创建
1. 字面量创建 快捷创建(不能拼接变量)
var a = 100;
var reg = /day/ig;
console.log(reg);
2. 构造函数创建 (可以拼接变量)
var a = 100;
var reg = new RegExp("d"+a+"y","ig");
console.log(reg);
3. 组合用法 (构造函数RegExp 也可以接收一个正则表达式)
var reg = new RegExp(/day/ig);
console.log(reg);
日期对象
日期对象 => 可以获取和设置时间
怎么创建日期对象?
构造函数创建 (获取|设置)
(1) 获取当前时间 => 中国标准时间(GMT(UTC) + 0800)
GMT(UTC) 世界时(格林威治) => Date对象记录着从1970年1月1日00:00:00开始以来的毫秒数
var date = new Date();
console.log(date);
(2) 设置一个时间
a. 接收一个时间格式的字符串(时间格式 "2021/10/11 12:12:12")
var date = new Date("2021-11-11 12:12:12");
console.log(date);
b. 多参数传参(分别指定 年月日 时分秒) =>
注意: 月份参数: 0-11 => 月份的参数 = 期望的月份 - 1
var date = new Date(2021,10,11,12,12,12);
console.log(date);
c. 可以接收一个毫秒数 (参数只有一个 且是number类型)
var date = new Date(0);
var date = new Date(1000000000000); // > 1970
var date = new Date(-1000000000000); // < 1970
console.log(date);
d. new Date()可以接收一个日期对象 => 可以得到一个与原日期 时间相同的新日期 (日期对象的拓展方法中 存在影响原日期的方法 => 为了不影响 先复制)
var date = new Date("2021-11-11 12:12:12");
var date1 = new Date(date); // date -> ms -> new Date(ms)
console.log(date);
console.log(date1);
字符统计
1. 已知字符串"aabccd"编程实现以下功能。
(1) 字符串去重 "abcd"
var str = "aabccd";
var uniStr = "";
for (var char of str) {
if (uniStr.indexOf(char) == -1) {
uniStr += char;
// uniStr = uniStr.concat(char);
}
}
console.log(uniStr); // "abcd"
(2) 统计每个字符出现的次数,结果显示 a2b1c2d1 字符统计(每个字符出现的总次数)
var countStr = "";
for(var i=0;i<uniStr.length;i++){ // "abcd"=> 每一个
var uniChar = uniStr.charAt(i); //"a"
var count = 0;
for(var j = 0; j < str.length; j++){
var item = str.charAt(j);
if(uniChar == item){
count++;
}
}
countStr += uniChar+count;
}
console.log(countStr);
var countStr = "";
for(var i=0;i<uniStr.length;i++){ // "abcd"=> 每一个
var uniChar = uniStr.charAt(i); //"a"
var reg = new RegExp(uniChar,"g"); // /a/g
var list = str.match(reg);
console.log(reg,list);
countStr += uniChar+list.length;
}
console.log(countStr);
var arr = [ "a" ,"a", "b" ,"c" ,"c" ,"d"];
var str = "aabccd";
var obj = {};
for (var char of str) { // "aabccd" => "a" "a" "b" "c" "c" "d"
if (obj[char]) { // 把每一个字符 作为对象的键名(键名唯一)
obj[char]++; // obj[char] = obj[char] + 1
} else {
obj[char] = 1;
}
}
console.log(obj);
var countStr = "";
for(var key in obj){
console.log(key,obj[key]);
countStr += key + obj[key];
}
console.log(countStr);
(3)(原始字符串:aaaabbbbbbbccdaaaaa;压缩后:a4b7c2d1a5) 压缩统计 (相邻字符重复的次数)
var str = "aaaabbbbbbbccdaaaaa";
var count = 0;
var countStr = "";
for(var i = 0; i < str.length;i++){
if(str.charAt(i) == str.charAt(i+1)){
count++;
}else{
count++;
countStr += str.charAt(i) + count;
count = 0; //重置为0 用于下次重新计数
}
}
console.log(countStr);
定时器
var timer = setInterval(function(){},1000)//设置定时器,间隔1000毫秒触发函数
clearInterval(timer)//清除指定定时器
设置计时器
把函数当成参数 传入到另一个函数中,由另一个函数代为执行 => 回调函数
可以理解为 => 提前规定好了要执行的内容(放在函数中)
setInterval(callbackFn,interval,arg1,arg2...argN); 每隔特定时间 指定 某个操作(函数)
callbackFn 传入一个函数用于指定每次间隔时间执行的内容 (提前指定了要执行的内容 => 函数(命名函数 匿名函数 => 把函数作为参数传入))
interval 间隔时间(单位是毫秒)
arg1,arg2...argN 作为callbackFn的实际参数传入
返回值 数字 => 计时器的编号
注意: 计时器从启动 到 开始执行 需要先等待对应的间隔时间
如果callbackFn需要接收参数:
(1) 可以接收一个函数调用形式的字符串 => 计时器内部可以将该字符串作为JS语法解析
var timer = setInterval( 'countDown("2021-11-11 00:00:00")' ,1000);
(2) 改为函数的嵌套调用 => 每隔一段时间执行匿名函数 => 调用countDown
var timer = setInterval( function(){
countDown("2021-11-11 00:00:00");
} ,1000);
(3) 如果 callbackFn需要接收参数 可以从第三参数开始 依次传入
var timer = setInterval( countDown ,1000,"2021-11-11 00:00:00");
需求 每隔一段时间再控制台打印 111
setInterval("console.log('hahaahhahahh')",1000)
setInterval(function(){
console.log(11111);
},1000)
setInterval(console.log,1000,1111,2222,3333);
模板字符串
ES6 模板字符串 可以借助插值语句${} => 拼接变量和执行简单表达式
日期对象的拓展方法_获取
var date = new Date(); //日期对象
console.log(date);
获取 年月日 星期 时分秒 毫秒
var year = date.getFullYear();
console.log(year);
获取月份 => 月份(0-11)
注意:如果要做展示效果 实际月份 = 获取的月份 + 1
var month = date.getMonth();
console.log(month);
console.log("实际月份:",month+1);
获取日期
var day = date.getDate();
console.log(day);
获取星期 => 星期(0-6 0:星期天)
var week = date.getDay();
console.log(week);
var hour = date.getHours();
console.log(hour);
var minute = date.getMinutes();
console.log(minute);
var second = date.getSeconds();
console.log(second);
var millisecond = date.getMilliseconds();
console.log(millisecond);
获取当前日期对应的总的毫秒数
var ms = date.getTime();
console.log(ms);
console.log("--------------------UTC--------------------------------");
var year = date.getUTCFullYear();
console.log(year);
获取月份 => 月份(0-11)
注意:如果要做展示效果 实际月份 = 获取的月份 + 1
var month = date.getUTCMonth();
console.log(month);
console.log("实际月份:",month+1);
获取日期
var day = date.getUTCDate();
console.log(day);
获取星期 => 星期(0-6 0:星期天)
var week = date.getUTCDay();
console.log(week);
var hour = date.getUTCHours();
console.log(hour);
var minute = date.getUTCMinutes();
console.log(minute);
var second = date.getUTCSeconds();
console.log(second);
var millisecond = date.getUTCMilliseconds();
console.log(millisecond);
日期对象的拓展方法_设置
设置日期对象的 年月日 时分秒 毫秒
返回值: 设置的时间 对应的 毫秒数
是否影响原日期对象 : 影响
!!!!!!!!!!
注意 设置月日 时分秒 毫秒 超出最大临界值 => 进一位 小于最小临界值 => 借一位
设置年份
var result = date.setFullYear(2500);
console.log(result);
console.log(date);
设置月份 参数范围(0-11)
var result = date.setMonth(0); // 2021-1-12
var result = date.setMonth(-1); // 2021-(-1)-12 => 2020-12-12
var result = date.setMonth(12); // 2021-(13)-12 => 2022-1-12
console.log(result);
console.log(date);
设置日期
本月的第0天 就是上个月的最后一天
下个月第0天 就是本月的最后一天
var result = date.setDate(1); // 2021-10-1
var result = date.setDate(0); // 2021-10-0 => 2021-9-30
var result = date.setDate(32) // 2021-10-32 => 2021-11-1
console.log(result);
console.log(date);
date.setHours(12);
date.setMinutes(21);
date.setSeconds(12);
date.setMilliseconds(123);
console.log(date);
设置日期对应的毫秒数
date.setTime(0);
console.log(date);
日期格式化_封装
2021-09-04 21:49:00
2021-09-04 21:49
2021-09-04
21:49:00
2021/09/04 21:49:00
2021/09/04 21:49
2021/09/04
封装一个函数 对时间格式化并输出 => 输出时 指定时间格式?
pattern 形参用于接收时间格式
date 选填(默认获取当前时间, 也可以传入一个事件格式的字符串,日期对象,毫秒数)
function dateFormat(pattern,date){
var pattern = "YY-MM-DD hh:mm:ss";
判断是否有无传参
if(date){ // 有参数 => 根据传入的得到一个新时间
date = new Date(date);
}else{ //没有 => 默认获取当前时间
date = new Date();
}
var year = date.getFullYear();
var month = date.getMonth()+1;
var day = date.getDate();
var hour = date.getHours();
var minute = date.getMinutes();
var second = date.getSeconds();
链式操作 本质replace() 方法返回的是:被替换后的新字符串 该字符串依旧可以调用replace方法
return pattern.replace("YY",year).replace("MM",beauty(month)).replace("DD",beauty(day)).replace("hh",beauty(hour)).replace("mm",beauty(minute)).replace("ss",beauty(second));
}
function beauty(num) {
return num < 10 ? "0" + num : num;
}
console.log(dateFormat("YY-MM-DD hh:mm:ss"));
console.log(dateFormat("YY-MM-DD hh:mm"));
console.log(dateFormat("YY-MM-DD"));
console.log(dateFormat("hh:mm:ss"));
console.log(dateFormat("YY/MM/DD hh:mm:ss"));
console.log(dateFormat("YY/MM/DD hh:mm:ss","2021-12-31"));
console.log(dateFormat("YY/MM/DD hh:mm:ss",1000000000000));
封装一个函数 对时间格式化并输出 => 输出时 指定时间格式?
pattern 形参用于接收时间格式
function dateFormat(){
var pattern = "YY-MM-DD hh:mm:ss";
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth()+1;
var day = date.getDate();
var hour = date.getHours();
var minute = date.getMinutes();
var second = date.getSeconds();
pattern = pattern.replace("YY",year); // 被替换后的新字符串 赋值给原来的变量
pattern = pattern.replace("MM",month);
pattern = pattern.replace("DD",day);
pattern = pattern.replace("hh",hour);
pattern = pattern.replace("mm",minute);
pattern = pattern.replace("ss",second);
console.log(pattern);
//链式操作 本质replace() 方法返回的是:被替换后的新字符串 该字符串依旧可以调用replace方法
pattern = pattern.replace("YY",year).replace("MM",month).replace("DD",day).replace("hh",hour).replace("mm",minute).replace("ss",second);
console.log(pattern);
}
设置日期时不影响如何原日期对象
var date = new Date();
console.log(date);
设置日期对象的 年月日 时分秒 毫秒
返回值: 设置的时间 对应的 毫秒数
是否影响原日期对象 : 影响
得到一个与原日期对象 时间相同的新日期对象
var date1 = new Date(date); // date => ms => 新日期对象
var result = date1.setFullYear(2500);
console.log(result);
console.log(date1);
console.log(date);
延时器
计时器 每隔一段时间 执行 特定的内容 (只要不清除 一直执行)
延时器 延迟一段时间 执行特定的内容 (只执行一次)
设置延时器
setTimeout(callbackFn,delay,arg1,arg2...argN)
callbackFn 传入一个函数用于指定等待特定时间后执行的内容 (提前指定了要执行的内容 => 函数(命名函数 匿名函数 => 把函数作为参数传入))
delay 延迟时间(单位:毫秒)
arg1...argN 如果callbackFn需要接收参数 则从第三参数开始依次向后传
返回值: 延时器的编号
清除延时器
clearTimeout(延时器的编号) 一般用于清除延时器改计时器
DOM初识
JS组成
ECMAScript =>ES5 (ES6)
BOM(Browser Object Model) 浏览器对象模型 => 提供了操作浏览器的接口和方法
DOM(Document Object Model) 文档对象模型 => 提供了操作文档的接口和方法
window => document => html => body => ...
HTML DOM 是关于如何获取、修改、添加或删除 HTML 元素的标准,即操作HTML的元素
简单的来说 HTML元素的增删改查
注意: 关于文档document
整个html页面载入到浏览器中 变成文档的一部分
通过文档可以访问页面中所有的元素 (动态地访问和更新文档的内容、结构和样式)
console.log(document);
JS新增节点的概念
根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点:
整个文档是一个文档节点 => document
每个 HTML 元素是元素节点 => h1-h6 p div ul li span
HTML 元素内的文本是文本节点 => 文本
每个 HTML 属性是属性节点 => class="" id="" title=""
注释是注释节点 =>
节点的本质 => 对象
层级关系(节点树中的节点彼此拥有层级关系。)
父节点
子节点
同胞节点
根节点(html) 根节点没有父节点
获取元素节点的方法
获取元素节点的方法
(通过文档获取 页面所有的元素)
document.getElementById(); 在文档中,通过id名获取元素 取得到=>元素 取不到:null
document.getElementsByClassName() 在文档中,通过class名获取元素 取得到=>集合 取不到:[]
document.getElementsByTagName(); 在文档中,通过标签名获取元素 取得到=>集合 取不到:[]
document.getElementsByName() 在文档中,通过name属性获取元素 取得到=>集合 取不到:[] (一般用于表单元素)
获取元素节点的方法_限制父元素
是否可以通过父元素来获取对应的子代元素 (限制查询范围)
可以通过父元素 来 获取子代元素 =>有局限性 (只能通过父元素获取 getElementsByClassName getElementsByTagName)
元素节点的方法
元素节点的方法 => 操作属性节点(属性的增删改 查)
属性节点 (写在标签内 和标签名以一个空格分隔) => 依存于元素节点
通过元素节点 相关的方法 操作属性节点
Element.getAttribute(key) 对应属性名获取属性值
Element.setAttribute(key,val) 对应属性名设置属性值 (没有就新增 有就修改)
Element.removeAttribute(key) 对应属性名删除属性
var one = document.getElementsByClassName("one")[0]; // 节点本质 => 对象
console.log(one);
获取
var _class = one.getAttribute("class");
console.log(_class);
var id = one.getAttribute("id");
console.log(id);
var title = one.getAttribute("title");
console.log(title);
设置(修改)
one.setAttribute("class","first");
one.setAttribute("id","demo");
one.setAttribute("title","你好");
console.log(one);
删除
one.removeAttribute("class");
one.removeAttribute("id");
one.removeAttribute("title");
console.log(one);
新增 (设置 没有就新增 => 有就修改)
one.setAttribute("class","first");
one.setAttribute("id","demo");
one.setAttribute("title","你好");
注意 H5开始,允许用户自定义属性(自己规定属性名和属性值)
(1) 以 data-属性名
(2) 自己随意定义 asd abc
one.setAttribute("asd","asd");
one.setAttribute("data-index","0");
var asd = one.getAttribute("asd");
var index = one.getAttribute("data-index");
console.log(asd);
console.log(index);
one.removeAttribute("asd");
one.removeAttribute("data-index");
console.log(one);
document.getElementsByClassName() 获取相同class属性的节点列表 IE8及以下不支持 封装一个方法 从页面的所有元素中 找到含有指定class名的元素 放到数组中 => 返回
function myGetElementsByClassName(className){
var className = "list"; //需要查找的class名
var list = document.getElementsByTagName("*"); //获取页面中所有的元素
console.log(list);
var arr = [];
for(var i=0;i<list.length;i++){
var ele = list[i];
console.log(ele);
var _class = ele.getAttribute("class");
console.log(_class);
if(_class){ // 有值 => 含有class名
var classList = _class.split(" ");
console.log(classList);
if(indexOf(classList,className)!=-1){
arr.push(ele);
}
}
}
return arr;
}
function includes(list,char){
var flag = false;
for(var i = 0; i < list.length; i++){
var item = list[i];
if(item === char){
flag = true;
break;
}
}
console.log(flag);
return flag;
}
返回某个元素在数组中第一次出现的位置 存在:返回下标 不存在:-1
function indexOf(list,char){
var index = -1;
for(var i = 0; i < list.length; i++){
var item = list[i];
if(item === char){
index = i;
break;
}
}
console.log(index);
return index;
}
querySelector和querySelectorAll
document.querySelector(selector); 单元素获取,单个元素=>直接返回 多个元素 => 默认返回集合中第一个
document.querySelectorAll(selector); 多元素获取 => 集合; 即便只有一个也会放到集合中(id也是如此)
元素查找_层级查找
节点
文档节点 元素节点 属性节点 文本节点 注释节点
层级关系
父节点 子节点 同胞节点
父
父节点 父元素 => 父节点和父元素没区别的
Element.parentNode
Element.parentElement
子
子节点 子元素
Element.childNodes 子节点(元素节点 文本节点 注释节点)
Element.children 子元素
第一个子节点 第一个子元素
Element.firstChild
Element.firstElementChild
最后一个子节点 最后一个子元素
Element.lastChild
Element.lastElementChild同胞
前一个 同胞节点 前一个 同级元素
Element.previousSibling 前一个节点
Element.previousElementSibling 前一个元素
后一个 同胞节点 后一个 同级元素
Element.nextSibling 后一个节点
Element.nextElementSibling 后一个元素
节点的新增_元素节点
document.createElement(tagName) 根据传入的参数(标签名) 创建一个对应类型 元素(节点)并返回 (创建的元素节点 不会自定放到页面中 而是存储在内存当中)
append 追加 prepend 预追加
放到父元素中 由父元素统筹
parent.appendChild(newNode) 向父元中追加一个新的节点(元素节点 文本节点 注释节点) => 放在父元素所有内容的最后方
parent.append(newNode|string) 向父元中追加一个新的节点(元素节点 文本节点 注释节点)或文本 => 放在父元素所有内容的最后方
parent.prepend(newNode|string) 向父元中预追加一个新的节点(元素节点 文本节点 注释节点)或文本 => 放在父元素所有内容的最前方
插入同级 由父元素统筹
parent.insertBefore(newNode,oldNode) 将一个节点(新的节点/已存在的) 插入到 另一个节点(已存在)的前面
节点的删除
节点的删除
(1) 自删 Element.remove() 元素自己删除自己
(2) 父删 parent.removeChild(node) 由父元素统筹
节点的修改
parent.replaceChild(newNode,oldNode) 用一个节点(新的节点/已存在的) 替换到 另一个节点(已存在)
节点的克隆
Element.cloneNode(bool)
Element.cloneNode(false) 默认false 只克隆当前元素及其相关属性 => 但是并不克隆子内容
Element.cloneNode(true) 既克隆当前元素及其相关属性 又克隆子内容
元素节点的属性
元素节点的属性 Element.xxx
tagName 获取元素的标签名 (只能取值 不能赋值) => 区分元素类型
innerHTML 获取和设置 元素内的html结构
innerText 获取和设置 元素内的文本结构
textContent 获取和设置 元素内的文本结构
outerHTML 获取和设置 元素本身及其内部的html结构
outerText 获取和设置 元素本身及其内部的文本结构
value 获取和设置 输入框的值
className 获取和设置 元素节点的 class名 (元素节点的属性)
classList 返回 由元素节点的class名形成的 集合
id 获取和设置 元素的 id 名
title 获取和设置 元素的 title
style 获取和设置内联样式
多元素绑定事件的问题
块级作用域 let声明的变量是局部的, 事件点击时没有li和i向外跳一层 找 包裹该事件的函数作用域
var liList = document.querySelectorAll(".nav li");
console.log(liList);
for (let i = 0; i < liList.length; i++) {
let li = liList[i];
li.onclick = function () {
// 自己没有向外跳一层 找块级作用域(循环当前的li和i)
console.log(li, i);
}
}
文档的可视宽高和实际宽高和滚动条的位置
文档的可视宽高 (只能取值 无法赋值)
常规浏览器 可视宽高 =>存在html中
document.documentElement.clientWidth
document.documentElement.clientHeight
低版本IE 可视宽高 =>存在body中
document.body.clientWidth
document.body.clientHeight
兼容
document.documentElement.clientWidth || document.body.clientWidth
document.documentElement.clientHeight || document.body.clientHeight
var clientWidth = document.documentElement.clientWidth || document.body.clientWidth;
var clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
文档的实际宽度和高度 (只能取值 无法赋值)
兼容
document.documentElement.scrollWidth || document.body.scrollWidth
document.documentElement.scrollHeight || document.body.scrollHeight
var scrollWidth = document.documentElement.scrollWidth || document.body.scrollWidth;
var scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
滚动条 距离文档左边(左移)和顶部(上升)的位置 (可以取值 也可以赋值)
兼容
document.documentElement.scrollLeft || document.body.scrollLeft
document.documentElement.scrollTop || document.body.scrollTop
window相关的事件
当窗口大小改变时 触发此事件
window.onresize = function(){
console.log("窗口大小发生改变",window.innerWidth,window.innerHeight);
}
当页面中的滚动条滚动时 触发此事件
window.onscroll = function(){
console.log("scrolling");
}
window.location相关的事件
location window.location
location的属性
protocol 设置或返回(取值和赋值)协议
hostname 设置或返回域名或主机名
port 设置或返回端口部分
host 设置或返回域名和端口
origin 设置或返回 协议 域名 和 端口
pathName 设置或返回 url的路径部分
search 设置或返回 url的参数数据部分
hash 设置或返回 hash值(url锚点部分)
href 设置或返回(取值和赋值)当前窗口的url地址
方法
reload() 刷新页面
replace() 用新的文档替换原本的文档(页面跳转) 替换当前的历史记录
assign() 用新的文档替换原本的文档(页面跳转) 追加当前url到历史列表中
鼠标相关的事件
鼠标相关的事件
onclick 鼠标单击(鼠标左键 按下之后在松开)
ondblclick 鼠标双击(鼠标左键 双击后在松开)
onmousedown 鼠标按下
onmousemove 鼠标移动
onmouseup 鼠标松开
onmouseover 鼠标划入
onmouseout 鼠标划出
键盘事件
onkeydown 键盘按键按下(所有的按键均可触发)
onkeyup 键盘按键松开(所有的按键均可触发)
onkeypress 键盘按键按下(和文本输入相关的按键均可触发 字母 数字 标点符号 space enter) => 表单输入
键盘事件的常见绑定方式
1. 绑定给文档 => 在页面的任何位置按下键盘均可触发
2. 绑定给表单元素 input textarea
document.onkeydown = function(event){ // event 事件对象
console.log("keydown",event.key);
console.log(event);
}
document.onkeyup = function(event){
console.log("keyup",event.key);
}
document.onkeypress = function(event){ // event 事件对象
console.log("keypress",event.key);
console.log(event);
}
绑定给表单元素
var demo = document.getElementById("demo");
demo.onkeydown = function(event){ // event 事件对象
console.log("keydown",event.key);
console.log(event);
}
demo.onkeyup = function(event){
console.log("keyup",event.key);
}
demo.onkeypress = function(event){ // event 事件对象
console.log("keypress",event.key);
console.log(event);
}
ES5 数组新增的拓展方法
数组遍历方法
forEach map filter some every reduce reduceRight
xxx(callback) 遍历数组 执行传入的回调函数
forEach 数组遍历
map 数组迭代(根据原数组得到新数组)
filter 数组筛选(筛选满足条件的元素 => 新数组)
some 数组判断(或) 是否存在满足条件的元素
every 数组判断(且) 是否所有的元素均满足条件
forEach(callback) 数组遍历
作用: 遍历数组,每次循环时执行传入的回调函数
参数:
callback 回调函数可以接收三个参数(item 循环当前元素,index 下标,array 原数组) (用户可以按照自己的需求 提前决定好要执行的内容)
返回值: undefined
var list = [2,8,4,6,5,7,9,3,1];
list.forEach(function(item,index,array){
console.log(item,index,array);
})
map(callback) 数组迭代(根据原数组得到一个新数组)
作用: 遍历数组,每次循环时执行传入的回调函数,接收回调函数的返回值,放到新数组中返回
参数:
callback 回调函数可以接收三个参数(item 循环当前元素,index 下标,array 原数组) (用户可以按照自己的需求 提前决定好要执行的内容)
返回值: 新数组
var list = [2,8,4,6,5,7,9,3,1];
var newArr = list.map(function(item,index,array){
console.log(item,index,array);
return item + 10;
})
console.log(list);
console.log(newArr);
filter(callback) 数组过滤/筛选
作用: 遍历数组,每次循环时执行传入的回调函数,回调函数返回一个条件,把满足条件的元素放到新数组中返回(如果返回值不是一个条件,会隐式转布尔值)
参数:
callback 回调函数可以接收三个参数(item 循环当前元素,index 下标,array 原数组) (用户可以按照自己的需求 提前决定好要执行的内容)
返回值: 新数组
var list = [2,8,4,6,5,7,9,3,1];
var newArr = list.filter(function(item,index,array){
console.log(item,index,array);
return item % 2 == 0;
return item % 2; // 0 1 => 奇数
})
console.log(list);
console.log(newArr);
some(callback) 数组(包含)
作用: 遍历数组,每次循环时执行传入的回调函数,回调函数返回一个条件,只要有一个元素满足条件则返回true 都不满足则返回false(如果返回值不是一个条件,会隐式转布尔值)
参数:
callback 回调函数可以接收三个参数(item 循环当前元素,index 下标,array 原数组) (用户可以按照自己的需求 提前决定好要执行的内容)
返回值: true|false
10 个数中是否存在大于60的数 假设法 假设不存在 => 找一个满足条件的
var list = [2,8,4,6,5,7,9,3,1];
var bool = list.some(function(item,index,array){
console.log(item,index,array);
return item > 5;
})
console.log(bool);
every(callback) 数组(都)
作用: 遍历数组,每次循环时执行传入的回调函数,回调函数返回一个条件,都满足条件则返回true 只要有一个元素不满足则返回false (如果返回值不是一个条件,会隐式转布尔值)
参数:
callback 回调函数可以接收三个参数(item 循环当前元素,index 下标,array 原数组) (用户可以按照自己的需求 提前决定好要执行的内容)
返回值: true|false
10 个数中是否都大于60的数 假设法 假设都大于60 => 找一个不满足条件的
var list = [2,8,4,6,5,7,9,3,1];
var bool = list.every(function(item,index,array){
console.log(item,index,array);
return item > 5;
})
console.log(bool);
reduce(callback,initValue) 数组累计
作用: 遍历数组,每次循环时执行传入的回调函数,回调函数返回一个结果,将该结果代入到下次函数调用
参数:
callback 回调函数可以接收三个参数( prev item index array) (用户可以按照自己的需求 提前决定好要执行的内容)
prev a.记录累加之前的初始值 (有初始值 就直接赋值,没有就默认是数组的第一个元素,从第二个开始遍历)
b.记录每次函数执行的返回值
item 循环当前元素
index 下标
array 原数组
initValue 可选参数 (用于指定prev的初始值
返回值: true|false
变量的解构赋值_数组解构
var arr = [1,2,3];
var [a,b,c] = [1,2,3];
console.log(a,b,c);//1,2,3
字符串
var [a,b,c] = "abc";
console.log(a,b,c);//a,b,c
伪数组
function fn(){
console.log(arguments);
var [a,b,c,d] = arguments;
console.log(a,b,c,d);
}
“…” 运算符
扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算, 用在数组中 将一个数组转为用逗号分隔的参数序列。
基础用法1:展开
const a = [2, 3, 4]
const b = [1, ...a, 5]
console.log(b);// [1, 2, 3, 4, 5]
基础用法2:收集
function foo(a, b, ...c) {
console.log(a, b, c)
}
foo(1, 2, 3, 4, 5); // 1, 2, [3, 4, 5]
基础用法3:把类数组转换为数组
const nodeList = document.getElementsByClassName("test");
const array = [...nodeList];
console.log(nodeList); // HTMLCollection [ div.test, div.test ]
console.log(array); // Array [ div.test, div.test ]
基础用法4:为数组新增成员
const peoples = ["jone", "jack"];
const mrFan = "Frank";
const all = [...peoples, mrFan];
console.log(all); // ["jone", "jack", "Frank"]
基础用法5:为对象新增属性
const obj = { name: 'jack', age: 30 }
const result = { ...obj, sex: '男', height: '178cm' }
console.log(result); // {name: "jack", age: 30, sex: "男", height: "178CM"}
基础用法6:合并数组或数组对象
const a = [1, 2, 3];
const b = [4, 5, 6];
const result = [...a, ...b]; // [1, 2, 3, 4, 5, 6]
基础用法7:合并对象
const people = {
name: 'Lucy',
age: 30,
sex: '女'
};
const base = {
age: 22,
job: 'teacher',
height: '168cm'
}
const all = { ...people, ...base };
console.log(all); // {name: "Lucy", age: 22, sex: "女", job: "teacher", height: "168cm"}
基础用法8 数组的深复制
var list = [1, 2, 3, 4, 5, 6]
var newList = list
var NewList = [...list]
console.log(list, "list")
console.log(newList, "newList")
console.log(NewList, "NewList")
console.log(list === newList) //ture
console.log(list === NewList) //false
基础用法9 伪数组转真数组
var liList = document.getElementsByTagName("li");
var arr = [...liList];
console.log(liList);
console.log(arr,Array.isArray(arr));
基础用法10 数组合并
var arr = [1,2,3];
var brr = [4,5,6];
var crr = [7,8,9];
var list = arr.concat(brr,crr);
var list = [...arr,...brr,...crr];
console.log(list);
基础用法11 对象的深复制
var obj = {
a: 1,
b: 2,
c: 3
}
var newObj = obj
var NewObj = {
...obj
}
console.log(obj, "obj")
console.log(newObj, "newObj")
console.log(NewObj, "NewObj")
console.log(obj === newObj) //ture
console.log(obj === NewObj) //false
箭头函数
ES6 允许使用“箭头”(=>)定义函数。
箭头函数 => 函数的简写
function fn(a,b){
console.log(a,b);
return a + b;
}
如何将普通函数改为箭头函数
1. 将函数改为匿名函数 (所有的箭头函数都是匿名函数)
2. 把匿名函数改为箭头函数 省略关键词function,在()后加 =>
3. 如果形式参数只有一个 可以省略小括号
注意: 如果没有形参,形参个数大于1 不能省略小括号如果没有只有一个,但是有默认值或参数结构 不能省略小括号
4. 如果函数的执行语句只有一条,且是return语句 可以省略 {} 和 return如果函数的返回值是一个对象 需要用()包裹
a. 改匿名函数
var fn = function(a,b){
console.log(a,b);
return a + b;
}
b. 改箭头函数
var fn = (a,b) => {
console.log(a,b);
return a + b;
}
console.log(fn(1,2));
c. 如果形式参数只有一个 可以省略小括号
var fn = (a) => {
console.log(a);
return a*10;
}
简写
var fn = a => { // 形式参数只有一个
console.log(a);
return a*10;
}
ES6_数组新增方法
Array.of()
Array.of() 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
Array.from()
Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组,浅拷贝的数组实例。所谓类数组对象,最基本的要求就是具有length属性的对象。
let string="hello world"
console.log(Array.from(string))//["h","e","l","l","o"," ","w","o","r","l",''d"]
let arrayLike = {
0: 'tom',
1: '65',
2: '男',
3: ['jane','john','Mary'],
'length': 4
}
console.log(Array.from(arrayLike)) // ['tom','65','男',['jane','john','Mary']]
find(callback)
可传入一个回调函数,用于找出第一个符合条件的数组成员
作用: 遍历数组,每次循环时执行传入的回调函数,回调函数返回一个条件,如果条件成立则返回直接返回该元素 否则返回undefined
var list = ["1", "2", "3", "4", "5", "6"]
var result = list.find(function (item) {
return item % 2 == 0 && item % 3 == 0
})
console.log(result)//6
findIndex(callback)
可传入一个回调函数,用于找出第一个符合条件的数组元素的下标
作用: 遍历数组,每次循环时执行传入的回调函数,回调函数返回一个条件,如果条件成立则返回直接返回该元素对应的下标 否则返回-1
var list = ["1", "2", "3", "4", "5", "6"]
var result = list.findIndex(function (item) {
return item % 2 == 0 && item % 3 == 0
})
console.log(result)//5
fill()
使用给定值,填充一个数组。
返回值 填充后的原数组
是否影响原数组 : 影响
var list = [2, 8, 4, 6, 5, 7, 9, 3, 1];
var result = list.fill(1);
console.log(result);//[1, 1, 1, 1, 1, 1, 1, 1, 1]
console.log(list);//[1, 1, 1, 1, 1, 1, 1, 1, 1]
注意: fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
var list = [2, 8, 4, 6, 5, 7, 9, 3, 1];
list.fill(1,2,5); // [2,5)从下标2开始包括下标2,到下标5的元素,不包括下标5
console.log(list);//[2, 8, 1, 1, 1, 7, 9, 3, 1]
includes()
方法用于判断字符串是否包含指定的子字符串。如果找到匹配的字符串则返回 true,否则返回 false。
注意: includes() 方法区分大小写。
var str = "Hello world, welcome to the Runoob.";
console.log(str.includes("world"))//true
console.log(str.includes("World"))//false
cookie
cookie的创建
1. cookie的存取都依赖于 document.cookie
2. cookie是以键值对(key=val)形式存在的字符串
3. cookie是一条一条的存储的
4. cookie 可以设置存储路径 和 过期时间(默认浏览器关闭 过期)
cookie的时效性(cookie可以设置过期时间)
默认情况下 cookie在关闭浏览器之后就过期了(浏览器会在关闭前删除过期cookie)
如果想设置 过期时间: 需要给cookie添加属性 exipres (exipres接收一个字符串类型的时间作为过期时间(世界时 date.toUTCString()))
cookie的跨页面访问 (cookie 可以设置存储路径)
cookie默认存储在当前文件所在的目录,同目录下所有的文件以及子目录下的文件均可以访问该cookie
如果想设置存储路径 需要给cookie添加属性 path (path用于接收一个根目录起的绝对路径)
setCookie("user", "b123123");//设置
deleteCookie("user");//单删
clearCookie();//清除全部
webStorage
webStorage 网页存储(H5新增)
WebStorage相关的属性和方法 => 数据的增删改查
属性
length 存储数据的数量
方法
setItem(key, value) —— 保存数据,以键值对的方式存储信息 (没有就设置 有就修改)
注意: 键值也只能是字符串类型 (数组/对象 => JSON.stringify() => JSON字符串)
getItem(key) —— 获取数据,将键值传入,即可获取到对应的value值
removeItem(key) —— 删除单个数据,根据键值移除对应的信息
clear() —— 删除所有的数据
key(index) —— 获取某个索引(index)的key
(localStorage(本地存储)和sessionStorage(会话存储) => 本质全局对象)
ajax
readyState 前端请求的状态
0:请求未初始化(只是创建了请求 还没有配置请求相关的信息 =>调用 open())。
1:请求已经建立 , 已经配置请求相关的信息 但是请求还未发送=>调用 send())。
2:请求已发送,正在处理中(通常现在可以从响应中获取内容头)。
3: 请求在处理中;通常响应中已有部分数据可用了,但是服务器还没有完成响应的生成。
4: 请求处理完毕,返回响应的结果 (结果不一定是成功的 )
status 后端响应的状态(结果不一定是成功的)
1** 信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作被成功接收并处理
3** 重定向,需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
5** 服务器错误,服务器在处理请求的过程中发生了错误
200:ok,页面正确打开,并得到完整的响应内容。
301:被请求的资源已永久移动到新位置
302:请求的资源临时从不同的 URI响应请求
304:缓存
404:页面不存在。
500:常指后端代码发生错误
503:由于临时的服务器维护或者过载,服务器当前无法处理请求。
ajax请求过程
1. 创建http请求(请求的载体)
2. 配置请求相关的信息 (请求的方式 请求的地址 是否异步(true))
3. 发送请求
4. 绑定事件,监听请求状态的改变 (页面加载时不会执行,状态改变时会执行)
5. 接收返回数据
var req = new XMLHttpRequest(); // 0
req.open("get", "../data/1.js", true); // 1
req.send(); // 1
req.onreadystatechange = function () {
if (req.readyState == 4 && req.status == 200) {
console.log(req.responseText);
// 后端返回的响应数据 可以是 txt/html/xml/json数据(json字符串)
// var result = req.responseText;
// demo.innerHTML = result;
}
}
注意:原生ajax get传参参数拼接在请求地址后面,post传参参数放在send()里面