JavaScript基础知识
一、对象的使用
1、创建对象
这里创建对象的方法我们采用最常用的一种:
//第一种
<script>var Person = {name: "zhangsan",age: "19",weight: "140",hight: "170",print:function(){console.log("hi");} };
</script>//第二种
<script>var obj = new Object();//创建了一个空的对象obj.name = "zhangsan";obj.age = 19;obj.sayHi = function () {alert("hi");}</script>//第三种,利用构造函数创建对象/*//构造函数的语法格式function 构造函数名(){this.属性名1 = 属性值1;this.属性名2 = 属性值2;this.属性名3 = 属性值3;this.方法名 = function(){}}//调用构造函数创建对象new 构造函数名();
*/script>function Star(name, age, sex) {this.name = name;this.age = age;this.sex = sex;this.sing = function () {alert("情深深雨濛濛")}}var ldh = new Star("刘德华", 50, "男");ldh.sing();</script>
注意这里在声明对象里面的方法的时候和之前说的不一样!!!
2、 调用属性和方法
<script>var Person = {name: "zhangsan",age: "19",weight: "140",hight: "170",print: function () {alert("hi")}};document.write(Person.name);document.write(Person.print())</script>
3、遍历对象
<script>var obj = {name: "zhangsan",age: 18,sex: "man"}for (var k in obj) {console.log(k);//这个是属性名console.log(obj[k]);//这个就是属性值}</script>
二、JavaScript中的内置对象
1、Math对象
<script>//Math不是一个构造函数,不需要new对象来使用//圆周率 Math.PI//最大值 Math.max(1,54,9); //54//Math.max(1,54,"asda"); //NaN//Math.max(); //-Infinity//绝对值 Math.abs(-1); ----1//绝对值 Math.abs('-1'); ----1 隐式转换,会把字符类型的数据转换为数字类型绝对值 Math.abs('asfdia'); ---- NaN//向下取整 Math.floor(1.9); ----1//向上取整 Math.ceil(1.1); ----2//四舍五入 Math.round(1.1); ---//随机数Math.random();// 此函数返回一个浮点数,返回一个[0,1)的数值console.log(Math.random() * 100);//得到两个数之间的随机数,并且包含这两个数function getRandom(min, max) {console.log(Math.floor(Math.random() * (max - min + 1)) + min);}getRandom(1, 10);</script>
①、猜数字游戏
<script>function getRandom(min, max) {return Math.floor(Math.random() * (max - min + 1) + min);}var randomNumber = getRandom(1, 10);while (true) {var inputNumber = +prompt("请输入一个整数");if (randomNumber > inputNumber) {alert("猜小了");} else if (randomNumber < inputNumber) {alert("猜大了");} else {alert("猜对了");break;}}</script>
2、Date对象
创建一个Date对象
var d = new Date();//表示当前代码执行的时间
//创建一个指定的时间对象
//需要在构造函数中传递应该表示时间的字符串作为参数
var d = new Date("12/03/2024 12:22:54");
//日期的格式:月/日/年 时/分/秒
①、常用的方法
var d = new Date();
d.getDate();//获取当前的日期是几号
d.getDay();//返回日期是一周中的哪一天,0-6,0表示周日
d.getMonth();//获取月份。0-11,0表示一月,11表示12月
d.getFullYear();//获取年份//时间戳指,1970年1月1日 0时0分0秒到当前日期所花的毫秒数
d.getTime();//获取当前日期对象的时间戳//获取当前的时间戳
time = Data.now();/*
利用时间戳来测试代码的执行时间
var start = Date.now();for(var i = 0;i<100;i++){console.log(i);
}var end = Date.now();
console.log(end-start);
*/
3、String对象
在底层字符串时以字符数组的形式保存的,下标从0开始
①常用的方法
var str = "hello world";str.length;//是记录字符串的长度str.charAt();//返回字符串中指定位置的字符str.charCodeAt();//返回指定位置字符的unicode编码String.fromCharCode();/根据字符编码区获取字符,得通过构造函数对象调用str.concat();//用来连接两个或者多个字符串str.indexOf();//该方法可以检索一个字符串中是否含有指定内容,如果字符串中含有该内容,则会返回其第一次出现的索引,如果没有,则返回-1,例:str.indexOf("h");
str.indexOf("d",0);//这第二个参数就是指定从第几次出现这个字符的位置开始查找,0表示从第一次指定字符出现的位置开始查找,1表示第二次
str.lastIndexOf();//该方法的和indexOf方法一样,只不过indexOf从前往后,lastIndexOf从后往前,也可以指定第二个参数
str.slice(0,2);//从字符串中截取指定的内容,不会影响原字符串,第一个参数是开始位置的索引(包括开始位置),第二个参数是结束位置的索引(不包括结束位置),如果省略第二个参数,则截取第一个参数后面所有的
str.substring();//也可以截取字符串,第一个参数是开始位置的索引(包括开始位置),第二个参数是结束位置的索引(不包括结束位置),如果省略第二个参数,则截取第一个参数后面所有的;但是不同的是,这个方法不能接收负值,有负值表示0
str.substr(1,2);//
//参数:1:截取开始位置的索引,2:截取的个数
str.split(",");//需要一个字符串作为参数,根据参数去拆分数组,返回值是一个数组
4、正则表达式
正则表达式用于定义一些字符串的规则:
①计算机可以根据正则表达检查一个字符串是否符合规则
//创建正则表达式的对象/*
语法:var 变量名 = new RegExp("正则表达式","匹配模式");使用typeof检查正则对象,会返回object在构造函数中,可以传递一个匹配模式作为第二个参数可以是:i:忽略大小写g:全局匹配模式
*/正则表达式的方法:test();用来检查一个字符串是否符合正则表达式的规则,符合返回true,否则返回false<script>var reg = new RegExp("a");//这个正则表达式用来检查字符串中是否含有avar str = "abc";var ret = reg.test(str);console.log(ret); // truevar reg = new RegExp("A","i");//这个正则表达式用来检查字符串中是否含有avar str = "Abc";var ret = reg.test(str);console.log(ret); // true</script>
②可以使用字面量创建正则表达式
/*①使用字面量创建正则表达式var 变量名 = /正则表达式/匹配模式例:<script>var reg = /a/iconsole.log(reg.test('bc'))//falseconsole.log(reg.test('ABC'))//trueconsole.log(reg.test('abc'))//true</script>②创建一个正则表达式用来检测字符串中是否有a或者b,使用|,或者使用[],[]里面的内容也是或者的意思,[bc]就是b或者c的意思<script>var reg = /a|b/iconsole.log(reg.test("a"))console.log(reg.test("bc"))</script>③创建一个正则表达式用来检测字符串中是否有字母<script>//[a-z]表示任意的小写字母,[A-Z]表示任意的大写字母,[A-z]表示任意的字母,[0-9]表示任意数字var reg=/[a-z]/console.log(reg.test('a'))//trueconsole.log(reg.test('A'))//false</script>④创建一个正则表达式用来检测字符串中是否有abc或者adc或者aec<script>var reg = /a[bde]c/console.log(reg.test('abc'))//trueconsole.log(reg.test('adc'))//trueconsole.log(reg.test('acd'))//falseconsole.log(reg.test('abd'))//falseconsole.log(reg.test('abf'))//false</script>⑤[^ ]表示除了<script>var reg=/[^ab]/console.log(reg.test("abc"));//true</script>
*/
③字符串和正则表达式一起使用
/*split()- 可以将一个字符串拆分成一个数组- 方法中可以传一个正则表达式作为参数,这样的方法将会根据正则表达式去拆分字符串例:根据任意的字符将字符串进行拆分注意:这个方法不指定全局匹配都会给拆完<script>var str = "1a2b3c4d5f6e7";var ret = str.split(/[A-z]/);console.log(ret.length);</script>search()例:可以搜索字符串中是否含有指定内容<script>var str = "hello abc bcd hello";var ret = str.search("abc"); console.log(ret);//等于6,是从下标0开始数的//如果搜索到指定内容返回第一次出现的索引,否则返回-1,他可以接受正则表达式去检索字符串注意:search只会查找第一个,即使设置了全局匹配例:搜索字符串中是否含有abc 或者 aec或者 afcvar str = "hello abc bcd afc aec";var ret = str.search(/a[bef]c/); </script>match()可以根据正则表达式,从一个字符串中符合条件的内容提取出来注意:一般情况下match只会找到第一个符合要求的内容,找到以后就停止检索,我们可以设置正则表达式为全局模式(写一个g),这样就会匹配到所有的内容可以为一个正则表达式设置多个匹配模式,且不用在意顺序match会将匹配到的内容封装到一个数组中,即使只有一个查询结果var str = "1a2b3c4d5f6e7";var ret = str.match(/A-z/);replace(参数1,参数2)可以将字符串中指定的内容替换为新的内容参数1:被替换的内容:可以接受一个正则表达式参数2:新的内容注意:默认只会替换第一个var str = "1a2b3c4d5f6e7";var ret = str.replace("a","@_@");ret = str.replace(/a/gi,"@_@");
*/
④量词
- 通过量词可以设置一个内容出现的次数,{a}表示正好出现n次
var reg = /a{3}/;//这个就是aaa的表达
- 注意:量词只对前面一个内容起作用
- {m,n}表示出现m到n次
- {m,}表示m次以上
- +表示至少一个,即{1,}
- *表示0个或者多个,相当于{0,}
- ?0个或者1个,相当于{0,1}
⑤检查一个字符串是否以一个字符开头或者结尾
-
使用^+字符
var reg = /^a/;//就是检查字符串是否是以一个字符开头
-
使用字符+$
var reg = /a$/;//检查字符串是否是以指定字符结尾
-
即使用^,有使用$
var reg = /^a$/;表示在正则表达式中只能有这个字符串
var reg = /^a|a$/;表示以a为开头或者以a结尾
⑥使用正则表达式检查电话是否符合规则
<script>var str = "18882636878";var reg = /^1[3-9][0-9]{9}$/;/*手机号规则:第一位以1开头第二位以3-9中的数字开头第三位及其以后只要是数字就行,但是最后必须以数字结尾*/console.log(reg.test(str));</script>
⑦检查一个字符串中是否含有.
- 但是在正则表达式中,光是写点表示任意字符
- 像这样的还有很多
- 表示\:使用两个\,即\
- 表示.:使用.
- \w:表示任意字母、数字、__
- \W:表示除了字母、数字、__
- \S:除了空格
- \s:表示空格
- \D:除了数字
- \d:任意的数字,0-9
- \B:除了单词边界
- \b:单词边界
- 创建一个正则表达式检测一个字符串中是否含有单词child
var reg = /\bchild\b/;
注意:使用构造函数的时候,由于它的参数是一个字符串,而\是字符串中转义字符,如果要使用\,就必须使用\\来代替
var str = "a.";
var reg = /\./;//要使用转义字符
console.log(reg.test(str));//true
⑧去除空格
- 去除字符串前后的空格
- 去除空格就是使用“”来替换空格
<script>var str = " hel lo ";//去除开头的空格var str = str.replace(/^\s*/, "");//去除结尾的空格var str = str.replace(/\s*$/, "");//去除两端的空格var str = str.replace(/^\s*|\s*$/g, "");console.log(str);</script>
⑨判断一个字符串是否是电子邮件
<script>/*电子邮件任意字母数字下划线 .任意字母数字下划线 @ 任意字母数字 . 任意字母(2-5位)*/var reg = /^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/;var email = "2326709846@qq.com";console.log(reg.test(email));</script>
三、DOM对象
节点
- 文档节点:整个html文档
- 元素节点:html文档中的html标签
- 属性节点:元素的属性
- 文本节点:html标签中的文本内容
<body><button id="butId" name="btn">我是按钮</button>
</body>
<script>//通过id获取元素var but = document.getElementById("butId");//修改元素内容but.innerHTML = "我是一个大but";//通过name属性获取元素var btn = document.getElmentsByName("btn");//通过标签名获取元素var btn = document.getElementsByTagName("button");
</script>
1、事件
//点击事件,当用户点击按钮,就会弹出对话框
<button id="butId" onclick="alert('你点我干嘛')">我是按钮</button>
//双击事件
<button id="butId" ondblclick="alert('你点我干嘛')">我是按钮</button>
//鼠标移动事件
<button id="butId" onmousemove="alert('你别动')">我是按钮</button>
但是以上的写法,不推荐使用
请看在script标签里面的处理事件
<body><button id="btnId">我是按钮</button>
</body>
<script>//获取按钮对象var btn = document.getElementById('btnId');//绑定单击事件btn.onclick = function () {alert('按钮被点击了');}
</script>
2、获取元素节点的子节点
<body><ul id="city"><li>成都</li><li>北京</li><li>上海</li><li>广州</li></ul>
</body>
<script>//获取所有的子元素的节点var city = document.getElementById("city");var lis = city.childNodes;/*这里的childNodes方法会获取包括文本节点在内的所有节点,注意并不是只有标签这里的文本节点就是回车键,所以length就是9*//*children属性可以获取的当前元素的所有子元素,但是不包括文本节点,就是只有标签*/var lis2 = city.children;//获取第一个子元素/*firstChild属性可以获取到当前元素的第一个子节点(包括空白文本节点)*/var firstli = city.firstChild;/*firstElementChild属性可以获取到当前元素的第一个子元素(不包括空白文本节点)但是不支持ie8及以下,如果需要兼容ie8及以下,则需要判断*/var first = city.firstElementChild;//获取最后一个子元素/*lastChild属性可以获取到当前元素的最后一个子节点(包括空白文本节点)*/var lastli = city.lastChild;/*lastElementChild属性可以获取到当前元素的最后一个子元素(不包括空白文本节点)但是不支持ie8及以下,如果需要兼容ie8及以下,则需要判断*/var last = city.lastElementChild;
</script>
3、获取父节点和兄弟节点
<body><ul id="city"><li>成都</li><li id="bj">北京</li><li>上海</li><li>广州</li></ul>
</body>
<script>//获取当前节点的父节点var bj = document.getElementById("bj");var bjParent = bj.parentNode;//console.log(bjParent);//获取当前节点的前一个兄弟节点,当然也可能获取到空白的文本var bjBorther = bj.previousSibling;//获取前一个兄弟元素,不包括空白的文本,但是ie8以及之前版本不支持var bjBorther2 = bj.previousElementSibling;//console.log(bjBorther);console.log(bjBorther.innerHTML);//获取当前节点的后一个兄弟节点
</script>
4、querySelect选择器选择元素
//document.querySelect这个方法,只会返回一个值,即使匹配的元素有多个也只会返回一个
//document.querySelectSAll这个方法可以返回多哥符合条件的元素
5、dom的增删改
①增
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><ul id="city"><li>成都</li><li>北京</li><li>上海</li><li>广州</li></ul><input type="button" id="btn" value="add" />
</body>
<script>var btn = document.getElementById('btn');btn.onclick = function () {//创建一个重庆节点添加到ul下面//创建li元素节点/*该方法用于创建一个元素节点对象,需要一个标签名作为参数,并将创建好的元素对象返回*/var li = document.createElement('li');//创建广州文本节点/**document.createTextNode*用来创建一个文本节点对象需要文本内容作为参数,并将创建好的文本节点对象返回*/var cqText = document.createTextNode('重庆');//将cqText设置为li的子节点/**** appendChild* 将一个节点对象作为子节点添加到父节点中* 需要一个子节点对象作为参数* 父节点.appendChild(子节点)*/li.appendChild(cqText);//获取city元素节点var city = document.getElementById('city');//将li设置为city的子节点city.appendChild(li);}</script></html>
②插入
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><ul id="city"><li>成都</li><li id="bj">北京</li><li>上海</li><li>广州</li></ul><input type="button" id="btn" value="insert" />
</body>
<script>//将重庆节点插入到北京前面var btn = document.getElementById('btn');btn.onclick = function () {//创建一个重庆节点添加到ul下面//创建li元素节点/*该方法用于创建一个元素节点对象,需要一个标签名作为参数,并将创建好的元素对象返回*/var li = document.createElement('li');//创建广州文本节点var cqText = document.createTextNode('重庆');//将cqText设置为li的子节点li.appendChild(cqText);//获取bj节点var bj = document.getElementById('bj');var city = document.getElementById('city');//将li节点插入到bj节点的前面/**** insertBefore可以在指定的子节点面前插入新的子节点* 语法:父节点.insertBefore(新节点,参照节点)* */city.insertBefore(li, bj);}</script></html>
④替换
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><ul id="city"><li>成都</li><li id="bj">北京</li><li>上海</li><li>广州</li></ul><input type="button" id="btn" value="replace" />
</body>
<script>//将北京节点替换为重庆节点var btn = document.getElementById('btn');btn.onclick = function () {//创建一个重庆节点添加到ul下面//创建li元素节点var li = document.createElement('li');//创建广州文本节点var cqText = document.createTextNode('重庆');//将cqText设置为li的子节点li.appendChild(cqText);//获取bj节点var bj = document.getElementById('bj');//获取cityvar city = document.getElementById('city');//开始替换/**** 可以使用指定的子节点替换已有的子节点* 语法* parentNode.replaceChild(newChild,oldChild);* parentNode:父节点* newChild:要插入的节点* oldChild:要替换的节点*/city.replaceChild(li, bj);}</script></html>
⑤删除
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><ul id="city"><li>成都</li><li id="bj">北京</li><li>上海</li><li>广州</li></ul><input type="button" id="btn" value="erase" />
</body>
<script>//将北京节点删除var btn = document.getElementById('btn');btn.onclick = function () {//获取bj节点var bj = document.getElementById('bj');//获取city节点var city = document.getElementById('city');//删除bj节点/***** removeChild* 可以删除一个子节点* 语法:* 父节点.removeChild(子节点)*///知道父元素删除子节点、、city.removeChild(bj);//不使用父元素删除子节点bj.parentNode.removeChild(bj);//这个最常用}
</script>
</html>
⑥关于innerHTML的用法
//读取city里面的html代码<body><ul id="city"><li>成都</li><li id="bj">北京</li><li>上海</li><li>广州</li></ul><input type="button" id="btn" value="read" />
</body>
<script>var btn = document.getElementById('btn');btn.onclick = function () {var city = document.getElementById('city');alert(city.innerHTML);}</script>//设置bj节点里面的html代码<body><ul id="city"><li>成都</li><li id="bj">北京</li><li>上海</li><li>广州</li></ul><input type="button" id="btn" value="edit" />
</body>
<script>var btn = document.getElementById('btn');btn.onclick = function () {var bj = document.getElementById('bj');bj.innerHTML = '南京';}
</script>//使用innerHTML实现添加的操作<body><ul id="city"><li>成都</li><li id="bj">北京</li><li>上海</li><li>广州</li></ul><input type="button" id="btn" value="add" />
</body>
<script>var btn = document.getElementById('btn');btn.onclick = function () {var city = document.getElementById('city');city.innerHTML += "<li>重庆</li>"}</script>
四、BOM对象
BOM对象就是浏览器对象,BOM对象比DOM大
1、定时器-延时对象
/*
仅仅只执行一次,代码延时
*/
setTimeout(回调函数,延时的时间(毫秒));var time = setTimeout(回调函数,等待的毫秒数);
//清除延时函数
clearTimeout(time);
2、location对象
关于location对象它拆分并保存了URL地址的各个组成部分//常用的方法和属性属性:①href:获取完整的URL地址,对其赋值时用于地址的跳转
//例:用户点击跳转,如果不点击,则在 5秒之后跳转,要求里面有秒数倒计时<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<style>span {color: red;}
</style><body><a href="http://www.itcast.cn">支付成功<span>5</span>秒钟跳转到首页</a>
</body>
<script>const a = document.querySelector('a');let num = 5let timer = setInterval(function () {num--;a.innerHTML = `支付成功<span>${num}</span>秒钟跳转到首页`if (num === 0) {clearInterval(timer);location.href = 'http://www.itcast.cn'}}, 1000);
</script>
</html>②search属性获取url(网址)中?后面的内容③hash获取地址(url)中的哈希值,#后面的内容④reload方法用于刷新当前新页面, 传入true参数时表示强制刷新
3、navigator对象
//该对象记录了浏览器自身的相关信息
常用的属性和方法:userAgent检测浏览器的版本和平台例:<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>!(function () {const userAgent = navigator.userAgent;//验证是否为Android或iphoneconst android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/);const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/);//如果是android或者iphone跳转到至移动站点if (android || iphone) {location.href = "http://m.itcast.cn";}})();</script>
</head>
<body>这是pc端
</body>
</html>
4、history对象
//该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
常用的方法或属性:back():后退功能forward():前进功能go(参数):参数1:前进一个页面,-1:后退一个页面
5、本地存储localStorage
本地存储只能存储字符串类型的数据
//存储一个名字 uname:dxy//用法:localStorage.setItem("键","值");localStorage("uname","dxy");//获取数据
//用法:var uname = localStorage.getItem("键");//删除数据//用法:localStorage.removeItem("键");
localStorage.removeItem("uname");
本地存储复杂数据类型
<script>var obj = {uname: "dxy",age: 18,sex: "男"}//本地存储复杂数据类型/**** 注意:* 第一个obj是键,第二个才是我们创建的对象值localStorage.setItem("obj", obj);* 但是无法直接使用所存的值* * 解决方法:* 需要将复杂数据类型转换为JSON字符串的数据类型* 语法:JSON.stringify(obj)*///存localStorage.setItem("obj", JSON.stringify(obj));//取//把JSON字符串转换为对象JSON.parse(localStorage.getItem("obj")); </script>
五、javascript进阶
1、垃圾回收机制
-
关于全局变量的话,一般不会回收(在关闭页面的时候进行回收)
-
一般情况下局部变量的值,不用了,会被自动回收掉
-
内存泄漏:程序中分配的内存由于某种原因未被释放获取无法释放
2、闭包
概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
简单理解:闭包=内层函数+外层函数的变量
简单的Demo理解:
function outer(){const a=1;function f(){console.log(a);}f();
}outer();
常见的Demo形式:(外部可以访问使用 函数内部的变量)
function outer(){const a=1;function f(){console.log(a);}return f;
}
const fun = oute();fun();
闭包的应用:实现数据的私有
function fn() {let count = 0function fun() {count++;console.log(`函数被调用${count}次`)}return fun;}const ret = fn();ret();//这个count不会被回收
3、箭头函数
语法:const fn = () =>{函数体}
fn();//只有一个形参的时候:可以省略小括号
const fn = x =>{console.log(x);
}
fn(1);//只有一个形参的时候:还可以省略大括号
const fn = x => console.log(x);
fn(1);//只有一个形参的时候,如果有返回值,可以省略return
const fn = x =>x+x
console.log(fn(1)); //箭头函数可以直接返回一个对象
const fn = (uname) => ({uname:uname})//第一个参数是属性名,第二个是属性值console.log(fn("刘德华"));//箭头函数没有arguments参数,但是有剩余参数
const getSum = (...arr) => {let sum = 0;for(let i;i<arr.length;i++){sum+=arr[i];}return sum;
}
getSum(2,3);//箭头函数的this指向的是上一层的this
<script>
const fn = () => {console.log(this);//window,并不是箭头函数里面的this,而是上一层,就是script标签里面的
}
fn();
</script>//对象方法箭头函数 this
<script>const obj = {uname:"dxy",sayHi:() => {console.log(this);//这个this就是obj}} obj.sayHi();
</script>const obj = {uname:"dxy",sayHi:function () {console.log(this)let i = 10;const count = () => {console.log(this)//这个this就是obj}count();}
}
obj.sayHi();
4、变量提升
在代码加载前,把变量声明提前,但是不会赋值
<script>//变量提升,但是只会提升到当前作用域,比如在函数里面,就只会提升到函数作用域//相当于 var name;但是不赋值console.log("我是" + name);var name = "小明";//结果就是我是undefined</script>
5、动态参数
<script>//动态参数function fun() {let sum = 0;for (var i = 0; i < arguments.length; i++) {sum += arguments[i];}console.log(sum);}fun(2, 3);</script>
6、剩余数组
<script>//剩余参数function fun(a, b, ...arr) {let sum = 0;for (let i = 0; i < arr.length; i++) {//arr中就是6和7sum += arr[i];}sum += a + b;console.log(sum);}fun(2, 3, 6, 7);//18</script>
7、数组解构
<script>//第一种let a = 1let b = 2//数组开头的前面必须加分号;[a, b] = [b, a];console.log(a, b)//第二种const [max, min, mid] = [100, 20, 50]console.log(max, min, mid)//100 20 50</script>
8、对象解构
<script>//对象解构 const { uname, age, sex } = { uname: "张三", age: 18, sex: "男" }/*等价于const uname = "张三"const age = 18const sex = "男"*/console.log(uname, age, sex)</script>
注意:
- 必须保证属性名和变量名一致
- 变量名可以重新命名,格式:旧属性名:新变量名
const {uname:username,age,sex} = {uname: "张三", age: 18, sex: "男"}
①解构数组对象
<script>const [{ uname, age }] = [{uname: "佩奇",age: 6}]console.log(uname, age);</script>
②多级对象解构
<script>const pig = {name: '佩奇',family: {mother: '米老鼠',father: '小红帽'},age: 6}const { name, family: { mother, father }, age } = pigconsole.log(name, mother, father, age)</script>
9、遍历数组元素(foreach)
<script>const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];arr.forEach(function (item, index) {//item是数组元素//index是数组元素的索引console.log(item, index);})</script>
10、构造函数
<script>//这样子就不用每次都写很多代码,可以直接封装成一个函数,new 对象时进行调用function Pig(name, age) {this.name = name;this.age = age;}const pig1 = new Pig('小猪1', 3);const pig2 = new Pig('小猪2', 5);console.log(pig1, pig2);</script>
11、原型对象
<script>function Person(name,age){this.name = namethis.age = age}//原型就相当于是一个对象,/*原型的作用:①共享两个对象中相同的方法②可以把不变的方法,直接定义在prototype对象上面注意:在使用原型的时候,将属性就写在构造函数中,而不变的方法就可以使用原型,这样就不用开辟新的地址了*///原型的使用/*注意:原型对象中的this还是指向的是实例化对象所以在构造函数和原型对象中,this都指向实例化对象*/Person.prototype.sayHi = function(){alert("hi")}const p1 = new Person("张三",18)p1.sayHi()</script>
①使用原型 对数组扩展方法:求和和求最大值、最小值
script>//最大值Array.prototype.max=function(){//展开运算符return Math.max(...this)//原型对象中的this指向实例化对象}//最小值Array.prototype.min=function(){//展开运算符return Math.min(...this)//原型对象中的this指向实例化对象}//求和Array.prototype.sum=function(){//箭头函数:一个以上的参数,就必须带小括号,只有一句代码,可以不用写大括号return this.reduce((prev,item)=>prev+item,0)}alert([1,2,3,4].min())alert([1,2,3,4].max())alert([1,2,3,4].sum())
</script>
12、原型对象中的constructor属性
<script>/*constructor属性是原型对象里面的属性作用:该属性指向该原型对象的构造函数function Person(){}Person.prototype.constructor===Person//是true*/function Star(){}Star.prototype={//这样就是直接赋值,就会覆盖掉之前的原本的属性、函数等,//所以要使用constructor属性让他找到自己的父亲//加上这行代码constructor:Star,//重新指回创造这个原型对象的构造函数sing:function(){console.log("sing")},dance:function(){console.log("dance")}}</script>
13、对象原型
在这里插入图片描述
对象都会有一个属性__proto__(两个下划线)指向构造函数的prototype原型对象,使得我们对象才可以使用构造函数prototype原型对象的属性和方法
注意:
- __proto__不是js的标准属性
- [[prototype]]和__proto__意义相同
- __proto__用来表明当前的实例对象指向哪个原型对象prototype
- __proto__对象原型里面也有一个constructor属性,指向创建该实例对象的构造函数
在这里插入图片描述
14、原型继承
<script>function Person() {this.eyes = 2;this.head = 1;}function Woman() {}//让woman继承personWoman.prototype = new Person();//再指回原来的构造函数Woman.prototype.constructor = Woman;const woman = new Woman();console.log(woman.eyes);
</script>
15、原型链
查找规则:
- ①当访问对象的属性时,先找该对象是否有这个属性
- ②如果没有就查找它的原型(就是__proto__指向的prototype原型对象)
- ③如果还没有就找原型对象的原型(Object的原型对象)
- ④以此类推直到找到Ojbect为止
- ⑤__proto__对象原型的意义就在于为对象成员机制提供一个方向,或者说一条路线
- ⑥可以使用instanceof运算符用于检查构造函数的prototype属性是否出现在某个实例对象的原型链上面
16、深浅拷贝
(1)浅拷贝
有两种方法
<script>const obj = {name: '张三',age: 18}//第一种使用展开运算符const o1 = { ...obj };console.log(o);//第二种使用Object.assign()const o2 = {};Object.assign(o2, obj);console.log(o2);
</script>
注意:浅拷贝在拷贝对象的时候,只能把对象里面单层的属性或方法拷贝,如果该对象中,还有对象,就实现不了拷贝的功能
(2)深拷贝
-
深拷贝通过使用函数递归的方式实现
-
使用lodash库方法
-
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script><script>const obj = {name: '张三',age: 18,family: {dad: "李四"}}//使用lodash库的cloneDeep方法深拷贝对象const newObj = _.cloneDeep(obj);console.log(newObj); // 输出:{ name: '张三', age: 18 }</script>
-
-
使用json实现深拷贝
-
<script>const obj = {name: '张三',age: 18,family: {dad: "李四"}}//使用json的形式实现深拷贝const obj1 = JSON.parse(JSON.stringify(obj));console.log(obj1);</script>
-
17、异常处理
(1)抛出异常
使用throw关键字,会终止程序,经常和error一起使用
-
<script>function func(x, y) {if (!x || !y) {throw new Error('x和y不能为空');}return x + y;}console.log(func());</script>
(2)try/cathch捕获异常
<script>function func() {try {const p = document.querySelector(".p");p.style.color = "red";} catch (error) {//拦截错误,不会中断程序的执行,提示浏览器提供的错误信息console.log(error.message)return} finally {//不管代码对不对,程序都会执行console.log("finally")}}
</script>
18、改变this指向
-
使用call方法(了解)
-
使用apply方法(理解)
-
语法:f.apply(thisArg,[argArray])
- thisArg:在fun函数运行时指定的this值
- argArray:传递的值,必须包含在数组里面
- 返回值就是函数的返回值
-
<script>const obj = {name: '123'}function f() {console.log(this);}f();f.apply(obj);</script>
-
实例:使用Math.max()求数组中的最大值
-
<script>console.log(Math.max.apply(Math, [1, 2, 3]));</script>
-
-
-
使用bind方法(掌握)
-
不会调用函数
-
语法:f.bind(thisArg,arg1,arg2,····)
-
thisArg:在fun函数运行时指定的this值
-
arg1,arg2:传递的参数
-
返回是一个函数,但是这个函数里面的this是被更改过的
-
<script>const obj = {age: 18}function f() {console.log("ad");}console.log(f.bind(obj))</script>
-
-
综上:call和apply在执行时,会调用函数,而且改变this指向,bind方法不会调用函数,并且会改变this指向