今日学习任务
[ ] 01-掌握内置对象的API
[ ] a.Date对象获取时间
- b.Array对象数组加工
- c.String对象字符串加工
- d.掌握json字符串的语法格式
- e.掌握JSON对象的字符串与对象转换应用
[ ] 02-JS作用域
[ ] a.理解js的局部作用域和全局作用域的关系
- b.理解js中作用域链的由来
- c.理解let的块级作用域应用
[ ] 03-补充知识
[ ] a.理解值传递和引用传递的区别
-
01-内置对象的API
1.1-Date日期对象
- 1.获取当前日期:
let date = new Date();
- 2.获取日期中的年月日时分秒
3.创建自定义日期
<script> /** * Date对象:js内置的用于获取当前日期与时间的对象 * 日期:只有年月日 2018/3/20 * 时间:只有时间 15:30:00 * 完整时间:年月日时 2018/3/20 15:30:00 */ //1.创建一个Date对象 let date = new Date(); /*时间日期打印*/ //2.打印当前完整时间: (1)默认显示当前电脑的时区时间 (2)打印date时会自动转为字符串 date.toString() console.log ( date );//Fri Mar 23 2018 20:45:15 GMT+0800 (中国标准时间) //3.打印日期:标准版本 console.log ( date.toDateString () );//Fri Mar 23 2018 //4.打印日期:本地版本(当前电脑) console.log ( date.toLocaleDateString () );// 2018/3/23 //5.打印当前时间:标准版本 console.log ( date.toTimeString () );//20:51:17 GMT+0800 (中国标准时间) //6.打印当前时间:本地版本 console.log ( date.toLocaleTimeString () );//下午8:51:17 /*年月日时打印*/ //1.打印当前年份 console.log ( date.getFullYear () );//2018 //2.打印当前月份 范围:0-11 代表 1-12月 console.log ( date.getMonth () );//2 代表下标2 也就是3月 //3.打印当前日 console.log ( date.getDate () );//23 //4.打印当前星期 范围0-6 代表星期天-星期六 console.log ( date.getDay () );//5 //5.打印时 console.log ( date.getHours () ); //6.打印分 console.log ( date.getMinutes () ); //7.打印秒 console.log ( date.getSeconds () ); /**创建自定义日期*/ let date1 = new Date(2020,0,1,12,3,5);//依次传入 年,月,日,时,分,秒 console.log ( date1 );//Wed Jan 01 2020 12:03:05 GMT+0800 (中国标准时间) let date2 = new Date("2022-05-06 12:03:35"); console.log ( date2 );//Fri May 06 2022 12:03:35 GMT+0800 (中国标准时间) </script>
1.2-Array数组对象
数组常用api
- 连接数组:
concat()
- 将数组元素拼接成字符串:
join()
- 删除数组最后一个元素:
pop()
- 往数组后面添加元素:
push()
- 翻转数组:
reverse()
- 删除数组第一个元素:
shift()
- 查找数组元素:
slice()
- 数组排序:
sort()
- 数组遍历:
forEach()
```html> 课堂小彩蛋 ```javascript //将数组第一个元素移动到最后面 let arr = [20,55,80,100,6];// [55,80,100,6,20] //将数组最后一个元素移动到最前面 let arr = [20,55,80,100,6];// [6,20,55,80,100]
1.3-String字符串对象
- 1.获取字符串长度:
str.length
- 2.获取字符串某一个下标字符:
str.charAt()
- 3.拼接字符串:
str.concat
- 4.判断字符串中是否包含某些字符串:
str.indexOf()
- 5.截取字符串:
str.substr()
- 6.修改字符串:
str.replace()
- 7.大小写转换:
str.toLowerCase()
小写str.toUpperCase()
大写 8.分隔字符串:
str.split()
```html<a name="8590091e"></a> ## 1.4-json字符串 - json字符串是目前前后端通信的数据载体 - 前端显示的数据是不会写死,都是后台得到 - 后台返回的数据格式最常用就是json字符串 - json字符串格式:与普通对象一样有属性名和值 - json字符串的属性名字和值都是使用双引号 - 严格要求:json字符串最后一个属性之后,不能有逗号 - json字符串的作用 - 跨平台数据识别统一化 ```javascript //后台通常返回数据是一个json字符串:为了让不同语言的平台达到数据统一性 //1.json字符串,无论键还是值,无论什么数据类型需要双引号(不识别数据类型,都是字符串) let json = `{ "name" : "张三", "age" : "18" }` //2.js对象是javascript语言中的对象(识别数据类型) let js = { name : "张三", age : 18, } //3.注意:js对象也是允许属性有引号的,而且不论单双引号都可以 let jsObj = { 'name':'张三', "age":18 } //打印输出 console.log ( json,typeof json ); // 字符串 console.log ( js ); console.log( jsObj ); //注意:如果json字符串外面没有引号或者反引号(模板字符串),那么就是js对象
1.5-JSON对象
js内部内置了一个JSON对象,专门用于处理JSON格式的数据
- JSON.parse(’json格式字符串‘):将json格式字符串转换成js可以识别的格式(对象或者数组)
- JSON.stringify(js对象或者数组):将js格式的对象或者数组,转换成json字符串
//1.json字符串,无论键还是值,无论什么数据类型需要双引号(不识别数据类型,都是字符串) let json = `{ "name" : "张三", "age" : "18" }`; //上述本质就是一个字符串,符合json格式,但是js依然不方便操作 //console.log(json.name); //undefined //2.JSON对象转换:将json字符串转成js的对象(当前是个对象格式) let jsonObj = JSON.parse(json); //3.js对象操作 console.log(jsonObj.name); //张三 //4.js将复杂数据传入给其他端(后台登陆) let loginObj = { username:'missyou', //JSON对象会自动给属性和值改成双引号 password:'missyoutoo' } //5.JSON将js对象转成json字符串 let loginJson = JSON.stringify(loginObj); console.log(loginJson);
1.6-JSON对象实现新闻展示
- 利用json字符串和JSON对象实现真实新闻展示
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .news { width: 400px; margin: 50px auto; text-align: left; } .news li { width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .news a { text-decoration: none; font-size: 14px; color: #222; line-height: 20px; } .news a:hover { color: #20a1f1; } </style> </head> <body> <script> //显示后台提供的新闻信息:news模拟后台返回的数据,为json格式字符串 //1.接收数据(模拟数据):外部数组,内部为对象 const news = `[ { "category": "要闻", "title": "牢记初心使命 实干笃定前行", "href":"https://news.ifeng.com/c/7wNelHB0SgK" }, { "category": "要闻", "title": "你以生命相托,我必全力以赴", "href":"https://news.ifeng.com/c/7wM1V3EzQBM" }, { "category": "要闻", "title": "中国无人战车正式服役:机枪显示惊人杀伤力", "href":"https://tech.ifeng.com/c/7wMT02ftUZ4" }, { "category": "健康", "title": "独家 | 武汉封城建议者:向武汉人民致敬,向援助武汉的人致敬", "href":"https://finance.ifeng.com/c/7wM0E6Bs8PI" }, { "category": "汽车", "title": "马斯克发飙:起诉当地政府!总部搬离加州!", "href":"http://auto.ifeng.com/c/7wM43afWMFs" }, { "category": "汽车", "title": "奇瑞真正的旗舰SUV,车长近5米+2.0T动力,气场不输路虎揽胜", "href":"https://auto.ifeng.com/c/7wIpWtWvHYv" }, { "category": "房产", "title": "广州即将推出9宗土地 涉及22.2万平米4宗宅地", "href":"https://gz.house.ifeng.com/news/2020_05_11-52744145_0.shtml" } ]`; //2.JSON转换:将json字符串转换成js的数组 const newsArr = JSON.parse(news); //3.制作字符串:包含div和ul的前半部分 let newsStr = ` <div class="news"> <ul> `; //4.遍历数组:构造li内部的a标签 for (let i = 0; i < newsArr.length; i++) { //newsArr[i]就是一条具体的新闻对象:{ "category": "要闻", "title": "牢记初心使命 实干笃定前行", "href":"https://news.ifeng.com/c/7wNelHB0SgK" } //newsArr[i].category是分类,newsArr[i].title是标题,newsArr[i].href是链接 //所以这样是不需要进行内部循环遍历的 //ES6模板字符串应用 newsStr += ` <li> <a href="${newsArr[i].href}">【${newsArr[i].category}】${newsArr[i].title}</a> </li> `; } // 补全标记 newsStr += ` </ul> </div> `; //输出 document.write(newsStr); </script> </body> </html>
02-js作用域及变量预解析
1.1-js作用域
- 1.作用域:变量起作用的范围
* 2.js中只有两种:全局作用域 局部作用域 * * 全局作用域:变量在任何地方起作用 * 全局变量:在函数外面声明 * 局部作用域:变量只能在函数内部起作用(又叫块级作用域) * 局部变量:在函数内部声明
<script> //1.全局变量 let a = 10; function fn ( ) { console.log ( a ); } fn(); //2.局部变量 function fn1 ( ) { let num = 10; console.log ( num ); } fn1(); console.log ( num ); </script>
1.2-作用域链
1.作用域链是怎么来的
- 默认情况下,我们的js代码处于全局作用域,当我们声明一个函数时,此时函数体会开辟一个局部作用域, 如果我们在这个函数体中又声明一个函数,那么又会开辟一个新的局部作用域,以此类推,就会形成一个作用域链
2.变量在作用域链上的访问规则
- 就近原则:访问变量时,会优先访问的是在自己作用域链上声明的变量,如果自己作用域链上没有声明这个变量,那么就往上一级去找有没有声明这个变量,如果有就访问,如果没有就继续往上找有没有声明,直到找到0级作用域链上,如果有,就访问,如果没有就报错
```html
<a name="f15d27d4"></a> ## 1.3-练习:作用域 - **记住:通常情况下,js中只有函数才可以开辟作用域,其他的语句都不可以** ```html <script> //案例1:函数中声明的变量才是局部变量,分支语句与循环语句的大括号中声明的变量仍然是全局变量 var num = 10; if(num > 0){ var sum = 20; } console.log ( sum ); //案例2:一般其他语言,循环变量i只能在for循环内部访问(局部变量),在js语言中是全局变量 for(let i = 0;i<5;i++){ } console.log ( i ); //案例3:函数中可以开辟作用域(局部作用域:块级作用域) let name = '张三'; function fn ( ) { name = '李四'; } fn(); console.log ( name ); </script>
1.4-js预解析
1.为什么要有预解析机制?
- 通过前面的学习我们知道,js代码是从上往下执行的,这样有什么不好的地方呢?
实际开发中,往往一个文件中js代码会有很多的函数,而如果我们都把函数的声明写在最上面,那么我们的业务逻辑就会在下面,这样的话开发效率不高
- 函数毕竟只是保存一段代码的,我们希望可以将函数写在页面的下面,而把一些业务逻辑功能写在代码上面,这样的话维护起来更方便
2.什么是预解析机制
- (1)其实js代码并不是从上往下执行的,这种说法不严谨
(2)预解析:JS在执行代码之前,会把变量的声明提前到所在作用域的最顶端
- a.只是声明提前(相当于提前开辟内存空间),变量的赋值与函数的调用还是在原地
- b.函数的声明也会提前
3.预解析的意义(好处)
//练习1
console.log(a);
var a = “我是变量”;
function a() {
console.log(“我是函数”);
};
console.log(a);/*预解析过程
var a;
function a(){ //变量的重复声明
console.log(“我是函数”);
};
console.log ( a ) ;
a = “我是变量”;//变量的重新赋值
console.log ( a ) ;- */
//练习2
let num = 10;
fun();
function fun() {
console.log(num);
var num = 20;
}console.log(num);
/预解析过程
var num;
fun();
function fun(){
var num;
console.log(num); //undefiend
num = 20;
}
num = 10;
console.log ( num );
/# 03-JS补充知识点 ## ==1.1-引用类型与值类型区别== * 引用类型:复杂数据类型,object(Object、Array、Date、RegRex、function) * 值类型:基本数据类型,五种:string number boolean undefined null * 为什么要有引用类型与值类型? * 假设将数据比喻为现实生活中的钱,当我们买东西的时候如果是比较少量的钱,一般我们使用钱包里面的现钱,这样更加快捷方便。如果我们买东西需要使用很多的钱,比如买一辆五百万的法拉利,那么使用现金就不方便,一般我们会把大量现金存到银行,然后使用刷卡来支付 * 在计算机的内存中,数据的存储也是如此。 * 1.内存主要有两部分:栈(钱包) 与 堆(银行金库) * 2.如果是值类型(基本数据类型),则数据保存在栈中(数据比较小,读取比较快捷方便) * 3.如果是引用类型(复杂数据类型),则将保存在堆中(银卡),而栈中存储的是这个数据的地址(钱包里面的银行卡) * 4.变量只能访问栈中的空间(买东西要么给现金要么刷卡,不会跟别人你把钱存到什么什么银行别人就会把东西给你) ![](day06.assets\0102-1589122327000.gif) ![](C:\Users\csumouse\Desktop\前端\JS基础8天\day08.assets\0103-1589122327001.gif) ```html <script> /* 引用类型:array,obejct 数据存储在堆中,地址存储在栈中 值类型:string number boolean undefined null 数据存储在栈中 区别:值类型:栈中存储的是数据,变量赋值时拷贝的是数据,修改拷贝后的数据不会对原数据造成影响 引用类型:栈中存储的是地址,变量赋值时拷贝的也是地址,修改拷贝后的数据会对原数据造成影响 */ //1.值类型:拷贝的是数据 var num1 = 10; var num2 = num1; //将num1的数据拷贝一份保存到num2中 num2 = 100; console.log ( num1, num2 ); //修改num2不会对num1造成影响 //2.引用类型: 拷贝的是地址 var arr1 = [10,20,30,40,50]; var arr2 = arr1; //将arr1的地址拷贝一份保存到num2中 arr2[0] = 100; console.log ( arr1, arr2 ); //修改arr2会对arr1造成影响 </script>
1.2-共享引用
- JS中实际对象传值不是真正的引用传值(传地址),而是传递引用的副本(call by sharing):按共享传递
对象赋值的本质是对象引用的副本
- 保存副本的对象如果是对对象本身进行操作:那么就是引用(操作原对象)
- 保存副本的对象如果是重新赋值:那么就重新开辟存储空间
//1.对象共享传递 var obj1 = { name: '我是本体' }; //2.对象引用(共享) var obj2 = obj1; var obj3 = obj1; //3.引用的改变效果:如果操作的是对象本身(属性或者方法)那么操作的是原对象obj1,如果把保存引用的变量赋值其他任何类型数据,那么都会重开内存(不影响obj1) obj2.name = '我是新本体'; //obj2操作的是obj1本身的对象,所以修改是共用的(不开辟新空间) console.log(obj1); //{name: "我是新本体"} obj3 = 1; //obj3独立开辟内存空间保存1,与obj1和obj2不再有关联 console.log(obj1); //{name: "我是新本体"} // 共享引用:共享引用是JS中复杂数据类型的本质传递方式而已
1.3-基本包装类型
本身是基本数据类型,但是在执行代码的过程中,可以调用相关的属性和方法
JS中有三种基本包装类型
- Number
- String
Boolean ```javascript /* //问题:为什么num是一个基本数据类型,可以像对象一样调用方法呢?
//基本数据类型 var num = 10; console.log ( typeof num ); num.toString () ; / 本质相当于执行了以下代码(JS解释器检测到num调用来toString()方法,所以快速处理了) (1) var num = new Number(10); // 创建对象 (2) num.toString(); // 调用对象方法 (3) num = null; // 删除对象 /
//对象类型 var num1 = new Number(10); /* 由于num1本身就是对象类型,所以这里可以直接调用,无需转换 */ num1.toString(); console.log ( num1 ); console.log ( typeof num1 );//object var str = '111'; str.toString(); /* (1)var str = new String('111'); (2)str.toString(); (3)str = null; */ var bol = true; bol.toString(); /* (1) var bol = new Boolean(true); (2) bol.toString(); (3) bol = null(); */
/* 基本包装类型和引用类型(new Number()/String()/Boolear()的区别 1.new产生的对象是长期占用内存,直到脚本结束 2.基本包装类型属于后台瞬发,用完就销毁了对象:对象 = null
所以:String/Number/Boolean,我们在开发中都是使用基本包装类型
*/
<a name="f541e778"></a> ## 1.4-数组去重 - 数组去重:将数组中重复的元素去掉 - JS数组没有删除具体元素的删除(只能删掉值,删不掉元素的索引),可以使用另外一个结构来进行存储 - 新数组 - 新对象 - JS数组虽然本质可以删除第一个和最后一个元素,可以利用这一特性,交换当前重复的元素到最后,然后进行删除(pop() 或者length--) ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <script> var arr = [20, 66, 88, 25, 66, 90, 88, 50];// [20,25,66,88,90,50] //1.排序法 : 最好理解 // //1.1 对数组排序 // arr.sort(function(a,b){ // return a-b; // }); // console.log(arr); // //1.2 声明空数组存储去重后的数组 // var newArr = []; // //1.3 遍历arr,检查arr[i]与arr[i+1]是否相等 // for(var i = 0;i<arr.length;i++){ // if(arr[i] != arr[i+1]){ // newArr[newArr.length] = arr[i]; // }; // }; // console.log(newArr); //2.开关思想(假设成立法) // //2.1 声明空数组存储去重后的数组 // var newArr = []; // //2.2 遍历arr,检查arr[i]在不在newArr中 // for (var i = 0; i < arr.length; i++) { // //开关思想 : 某种操作结果只有两种清空。布尔类型存储两种情况。 // //1.声明开关 // var single = true;//假设不在 // //2.遍历newArr检查 只要与arr[i]相等 // for(var j = 0;j<newArr.length;j++){ // if(arr[i] == newArr[j]){ // single = false; // break;//只要发现重复元素,后面没有必要比较 // }; // }; // //3. 根据开关结果实现需求 // if(single){ // newArr[newArr.length] = arr[i]; // }; // }; // console.log(newArr); //3.indexOf : 常用 // //2.1 声明空数组存储去重后的数组 // var newArr = []; // //2.2 遍历arr,检查arr[i]在不在newArr中 // for (var i = 0; i < arr.length; i++) { // if(newArr.indexOf(arr[i]) == -1){//不在 // newArr.push(arr[i]); // } // }; // console.log(newArr); //4.对象法 var arr = [20, 66, 88, 25, 66, 90, 88, 50]; /* 核心思路:利用对象的属性名不能重复 对象的取值赋值特点 取值 : 存在,取值。 不存在,取undefined 赋值 : 存在,修改。 不存在,动态添加 1.声明空对象 : 检查数组元素是否重复 (元素作为属性名,检查对象有没有这个属性) 2.声明空数组 :存储去重后的数组 3.遍历arr,检查arr[i]是否重复 */ var obj = {}; var newArr = []; for(var i = 0;i<arr.length;i++){ //检查对象有没有 arr[i] 这个属性? if(obj[arr[i]] == undefined){//未重复 newArr.push(arr[i]); obj[arr[i]] = 1;//这里赋值目的是为了下一次取值,不是undefined } }; console.log(newArr); //5.重复元素自我交换删除法 /* 核心思路:判定元素在数组中查到的位置是否是自身(元素是一定能找到的) * 如果是自身:说明当前元素还没有重复 * 如果不是自身:说明当前元素在前面已经存在过:交换最后一个元素,然后把最后一个删除 步骤: 1.遍历数组的每一个元素 2.判定当前遍历的元素在当前数组中存在的位置,判定位置是否是当当前自己的位置 2.1.是自己位置,说明前面没有重复,忽略 2.2.不是自己位置,说明前面已经存在: 2.2.1交换最后一个元素过来 2.2.2然后删除 2.2.3最后一个元素有可能已经与前面重复了,为了不跳过当前新交换的元素,重新从当前元素开始检索 */ arr = [1,1,2,3,5,0,1]; for (var i = 0; i < arr.length; i++) { //判定当前元素在数组中找出的位置 if (arr.indexOf(arr[i]) != i) { //说明不是自己:前面已经存在过 //交换最后一个元素过来(因为最后一个可以删除 var temp = arr[i]; arr[i] = arr[arr.length - 1]; arr[arr.length - 1] = temp; //删除最后一个元素:两种方式都可以 // arr.pop(); arr.length--; //最后一个元素有可能已经与前面重复了,所以为了保证安全,被交换过来的元素还要重新经受考验 i--; } } //注意:以上方式会改变数组中原来元素的顺序位置 </script> </body> </html>
今日课后作业
1.给定一个字符串如:“abaasdffggghhjjkkgfddsssss3444343”问题如下:?
- 输出字符串的长度?
- 取出指定位置的字符,如:0,3,5,9等?
- 查找指定字符是否在以上字符串中存在,如:i,c?,b等?
- 替换指定的字符,如:g替换为22,ss替换为b等操作方法?
- 截取指定开始位置到结束位置的字符串,如:取得1-5的字符串(包括下标5)
找出以上字符串中出现次数最多的字符和出现的次数?
- 遍历字符串,并将遍历出的字符两头添加符号“@”输出至当前的文档页面。
- 2.已知有字符串foo=”get&element&by&className”,写一个function将其转化成驼峰表示法”getElementByClassName
- 1.获取字符串长度:
- 连接数组:
- 1.获取当前日期: