学习网站
安装node
Window+R->cmd->node -v返回版本号
vsCode(js文件)右键->在集成终端中打开,安装完调试node -v返回版本号
(node js文件名)
ES5回顾
ECMAScript 和 JavaScript 的关系 :前者是后者的规格 ,后者是前者的一种实现 。
ES6与ES5的关系 :ES6是ES5的语法糖 ,即ES6是在ES5的基础上进行封装 ,多数代码都可以用ES5实现的,方便使用。
ES6与ES7的关系 :与ES6相比ES7增强了关键词async的功能 ,并且可以使用await ,轻松直接调用函数 来实现异步调用同步化 。
ECMAScript 版本历史 • ECMAScript 1.0(1997) • ECMAScript 2.0(1998) • ECMAScript 3.0(1999) • ECMAScript 5.0(2009/12) • ES6(ECMAScript 2015年 6月) • ES 2016(ES7) • ES 2017 (ES8) • ES 2018 (ES9) • ES 2019 (ES10) • ES 2020
严格模式
严格模式的关键词:‘use strict’;
变量必须先声明 再使用。
严格模式下,函数 本身不能使用this 关键词。
严格模式下eval()存在作用域 。
eval()函数的作用?
var age= 20;
eval( "var age=30;console.log(age);" ) ; //将字符串代码转换为可执行代码。
console.log( age) ;
JSON对象的常用方法
JSON.parse()将 类似数组或对象的字符串转化为真正的对象或数组 。
JSON.stringify()将 数组或对象转化为字符串
拷贝数组或对象 ,将JSON.parse()和JSON.stringify(),联合使用 (嵌套)可以实现拷贝功能,注:其实现的是深拷贝 。
深浅拷贝的核心思想? ------深浅拷贝的区别:深值浅址
如何实现深拷贝 ?将JSON.parse()和JSON.stringify(),联合使用(嵌套)可以实现拷贝功能
var arr= [ 1,2,3,4,5,6] ;
console.log( typeof JSON.stringify( arr)) ; //string将数组或对象转化为字符串
console.log( typeof JSON.parse( JSON.stringify( arr)) ) ; //object将类数组或类对象转化为数组或对象。
var newArr= JSON.parse( JSON.stringify( arr)) ; //作用:实现了数组或对象的拷贝,此方法是深拷贝。
newArr[ 3] = "ssssss" ;
console.log( arr) ; //[ 1,2,3,4,5,6]
console.log( newArr) ; //[ 1,2,3,'ssssss' ,5,6]
Object拓展
create()方法与defineProperties()的区别?
Object.create()方法 ,给参数一 原对象添加新的属性 并且生成新的对 象,此方法是深拷贝
Object.defineProperties() ,给对象添加新的属性 ,生成的新对象中,原对象的属性值是浅拷贝
参数一:原对象
参数二:新的添加的属性对象 ,注:defineProperties()会改变原对象 。
var user= {
username:"rypy" ,pwd:123456} ;
//1、create( ) 方法,给原对象添加新的属性,并且生成新的对象,深拷贝
//参数一是原对象
//参数二是添加新的属性的设置
var newUser= Object.create( user,{
sex:{
value:"男" ,//设置新属性的值
writable:true,//设置当前新添加的属性是否可以修改,默认值是false
configurable:true,//设置当前新添加的属性是否可以删除,默认值是false
enumerable:true//设置当前新添加的属性是否支持可枚举( 支持for循环输出) ,默认值是false
}
} ) ;
console.log( user) ; //{
username:"rypy" ,pwd:123456}
newUser.sex= "女" ;
delete newUser.sex;
console.log( newUser) ; //{
} 其原型中存在{
username:"rypy" ,pwd:123456}
for( var item in newUser) {
console.log( newUser[ item] ) ; //rypy 123456
}
//2、defineProperties( ) 方法给对象添加新的属性,它是一种浅拷贝
//参数一:原对象
//参数二:添加新的属性
var newUser= Object.defineProperties( user,{
sex:{
set( value) {
//设置新属性的值
this.sexValue= value;
} ,
get( ) {
//返回新属性的值,供外面使用
return this.sexValue;
}
}
} ) ;
newUser.sex= "男" ;
console.log( user) ; //{
username: "rypy" , pwd: 123456, sexValue: "男" }
console.log( newUser) ; //{
username: "rypy" , pwd: 123456, sexValue: "男" }
newUser.sex= "女" ;
console.log( user) ; //{
username: "rypy" , pwd: 123456, sexValue: "女" }
console.log( newUser.sex) ; //女
//create( ) 方法与defineProperties( ) 方法的区别?
//在js语法中常见的添加对象属性的方式有哪些,区别在于?
Array拓展
arr.forEach() :循环遍历 输出数组,不会生成新的数组 ,回调函数的参数一是元素的值 ,参数二是元素的下标 。
arr.map() :循环遍历输出数组,并根据return返回值生成新的数组 ,回调函数的参数一是元素的值 ,参数二是元素的下标 。注:map生成的新的数组跟原数组的个数是相同的。
arr.filter() :循环遍历输出数组,并根据return返回值的布尔类型 (即如果是true添加新数组,如果是false则会忽略),返回满足条件的原数组的值 ,回调函数的参数一是元素的值 ,参数二是元素的下标 。注:filter()可以实现数组的过滤 功能
var arr= [ 1,2,3,4,2,4,5] ;
//1、forEach( ) ,在回调函数中,循环输出数组的元素和下标,此方法没有返回值,也不会生成新的内容
//item,数组中的元素
//index,数组的下标
var arrEach= arr.forEach( function( item,index) {
//console.log( item,index) ;
// return "aaa"
} ) ;
console.log( arrEach) ; //undefined
//2、map( ) ,在回调函数中,循环输出元素和下标,并且根据return 关键词的返回值,会生成新的数组,数组的个数与原数组一致。
//item,数组中的元素
//index,数组的下标
var newArr= arr.map( function( item,index) {
//console.log( item,index) ;
return item+index;
} ) ;
console.log( newArr) ; //[ undefined,undefined,undefined,undefined]
//3、filter( ) ,在回调函数中,循环输出元素和下标,并且根据return 关键词的boolean类型,生成新的数组,如果为true添加到新的数组,false则被过滤掉。
//item,数组中的元素
//index,数组的下标
var arrFilter= arr.filter( function( item,index) {
console.log( item,index) ;
return item>= 4;
} ) ;
console.log( arrFilter) ;
Function拓展
bind()方法 ,将函数中的this绑定 给对象。参数一是绑定的对象 ,剩下的参数是需要给函数传递的值 。
call和apply与bind的区别?
call和apply都是改变this指向 ,bind将函数中的this绑定给对象
//bind将参数一,绑定函数的this指向。参数二.. .. .. 参数n,是可以给函数传递值
//bind函数的功能是将函数与对象进行绑定操作。
function f( sex) {
this.usename= "rypy" ;
this.age= 20;
this.sex= sex;
}
var obj= {
} ;
f.bind( obj,"男" ) ( ) ;
console.log( obj) ; //{
usename: "rypy" , age: 20, sex: "男" }
//call、apply和bind的区别?
对象的特例扩展
for of 自动循环输出数组中的元素
Object.keys() ,可以以数组的形式获取 对象中的键名
Object.values() ,可以以数组获取 对象中的键值
Object.entries() ,以二维 数组的形式,将对象中的每个键名和键值 ,进行数组分解。
var arr= [ 1,2,3,3,4,5,6] ;
for( var item in arr) {
console.log( arr[ item] ) ;
}
for( var item of arr) {
//for.. .of,可以直接遍历元素
console.log( item) ;
}
var user= {
username:"rypy" ,pwd:123456,sex:"男" } ;
//Object.keys( ) ,可以将对象中的键名生成数组,并且可以使用for.. .of进行遍历输出
for( var item of Object.keys( user)) {
console.log( item) ;
}
//Object.values( ) ,可以将对象中的值生成数组,并且可以使用for.. .of进行遍历输出
for( var item of Object.values( user)) {
console.log( item) ;
}
//Object.entries( ) ,可以将对象中的键值对生成数组,并且可以将键名和键值,再次生成数组
console.log( Object.entries( user)) ;
for( var item of Object.entries( user)) {
console.log( item) ;
}
for( var [ item,index] of Object.entries( user)) {
console.log( item,index) ;
}
//作业一:
//将 对象 user= {
username:"rypy" ,pwd:123456,sex:"男" } ;
//转化为字符串 username= "rypy" ,pwd= 123456,sex= "男"
//String.subString( ) ,if( ) typeof Object.entries( )
ES6
顶层对象 在浏览器环境 ,顶层对象指的是window 对象和_self
,在Node 中,顶层对象指的是global 对象(可跨平台)。ES2020在语言标准的层面,引入globalThis作为顶层对象,在任何环境 下,globalThis:ES2020语法新定义的通用顶层对象globalThis 都是存在的,都可以从它拿到顶层对象,指向全局环境下的this。
let和const
let 声明变量
const 声明常量 :定义的变量必须要在声明的时候初始化,初始化以后不能更改。
let和const的特性
let与const定义的变量是块级作用域 。
块级作用域 { }
ES5 中作用域有:全局作用域、函数作用域。没有块作用域的概念。
ES6 中新增了块级作用域。块作用域由 { } 包括,if语句和 for语句里面的{ }也属于块作用域
let与const定义的变量,不存在变量提升 ,即TDZ暂时性死区 。
同一作用域内,不能重复声明
let与var的区别?重要1
let与const定义的变量是块级作用域。var没有块级的概念
let与const定义的变量,不存在变量提升,即TDZ暂时性死区。 var有变量提升
同一作用域内,不能重复声明。var可以重复声明
const定义常量 (闭包解决变量不提升,声明变量let形成块级作用域)
for( var i= 0; i< 10; i++) {
var i= "rypy" ;
console.log( i) ; //rypy 只var一个分区
}
for( let i= 0; i< 10; i++) {
let i= "rypy" ;
console.log( i) ; //10个rypy 每let一次创一个分区,一共创了10个
}
// {
// let i= 0; i< 10; i++
// {
// let i= "rypy" ;
// console.log( i) ;
// }
// }
var arr= arr1= [ ] ;
for( var i= 0; i< 10; i++) {
arr[ i] = function( ) {
//匿名函数
console.log( i) ;
}
}
arr[ 8] ( ) ; //10 var了一个分区,循环对他赋值,最后为10,不管选择索引值为几,都为10
for( let i= 0; i< 10; i++) {
arr[ i] = function( ) {
//匿名函数
console.log( i) ;
}
}
arr[ 8] ( ) ; //8 let了10个分区,选择索引值为8的分区
//let 定义变量的关键词
let a= 20;
a= 30;
console.log( a) ;
//const 定义常量的关键词,定义必须初始化,且值不能更改。
const a= 20;
a= 30;
console.log( a) ;
//let和const的特点
//1、块级作用域
{
var a= 20;
console.log( a) ; //20
}
console.log( a) ; //20
{
let a= 20;
console.log( a) ; //20
}
console.log( a) ; //报错
//2、变量不可提升。TDZ( 暂时性死区) ,使用let和const定义的变量,在进入当前作用域代码块的时候会预加载,加载到缓存区,所以形成死区域,从而造成变量的死区。
{
console.log( a) ; //undefined
var a= 20;
}
{
console.log( a) ; //报错。
console.log( "dddddd" ) ;
console.log( "dddddd" ) ;
console.log( "dddddd" ) ;
let a= 20;
}
//3、同一作用域,let和const声明的变量,不能重复声明。
{
var a= 20;
var a= 30;
}
{
let a= 20;
let a= 30;
}
// let和var 定义变量/var 和const的区别?
解构赋值、默认值
解构赋值的概念
ES6 允许按照一定模式(即规则 ),从数组和对象中提取值 ,对变量进行赋值 ,这被称为解构赋值(Destructuring)。
数组解构赋值
数组的解构赋值,规则:先找[ ],再找",";进行对应匹配
赋值时
代码运行是从上到下,从左到右。
在ES6中undefined 是关键词(没有null),当与默认值同时存在的时候,默认值的优先级高。
在解构赋值的过程中,值的优先级高于函数调用 。
//数组的解构赋值
//形式:let [ 变量名] = [ 需要解构的内容]
//规则:先找[ ] ,再找 , 接着进行一对一匹配
let [ a,b,c] = [ 1,2,3] ;
console.log( a) ;
console.log( b) ;
console.log( c) ;
let [ a,,c] = [ 1,2,3] ; //不完全解构
console.log( a) ;
//console.log( b) ; //undefined,如果b未声明,则会直接报错//b is not defined
console.log( c) ;
let [ a,c] = [ 1,2,3] ; //不完全解构
console.log( a) ;
console.log( c) ;
//数组解构赋值和默认值
//形式 let [ 变量名= 默认值] = [ 值] ;
let [ foo = true] = [ undefined] ; //如果变量存在默认值,且解构赋值对应的值是undefined默认值优先。
console.log( foo) ;
let [ x = 1] = [ null] ; //注:ES6中只有一个未定义关键词undefined
console.log( x) ;
let [ x = 1, y = x] = [ 2] ;
console.log( x,y) ;
let [ x = y, y = 1] = [ ] ;
function f( ) {
//当默认值为函数的时候,如果解构赋值不是undefined,则解构赋值优先
console.log( 'aaa' ) ;
}
let [ x = f( ) ] = [ 1] ; //1
let [ x = f( ) ] = [ ] ; // aaa undefined
console.log( x) ;
对象解构赋值
对象的解构赋值,规则:先找{},在找键名,注:键名不区分先后顺序 。
对象解构中
对象的解构赋值可以从对象中解构方法 ,采用方法名直接解构 即可。
在解构赋值声明变量的时候,可以采用:对方法或变量进行重命名,注(:前面的变量只有传递特性或值的作用,传递完成立即销毁 )。
注意:在js中默认{}代码块,所以在运行对象的解构赋值的时候如果前面没有声明关键词,则会把{}识别代码块。如果需要解构赋值必须()
let {
log} = console;
log( "sssss" ) ; //相当于console.log( "sssss" ) ;
let {
log:a} = console;
a( "vvvvvv" ) ; //vvvvvv
log( "bnnnnnn" ) ; //log is not defined
( {
x} = {
x:1} ) ;
console.log( x) ;
//对象的解构赋值
//形式 ;let {
键名:变量的名字} = {
键名:值}
//规则:先找{
} ,再找, 再找键名
//注:传递值的键名用过,即销毁
//注:当键名和变量名为同名的时候,写一个即可
//注:当定义对象的变量名和赋值分开书写的时候,对象的解构赋值,需要用( ) 包裹起来,否则程序会默认把{
} ,识别为代码块。
//形式一
let {
username:haha} = {
username:"rypy" }
console.log( haha) ;
//形式二
let {
username} = {
username:"rypy" } //相当于 let {
username:username} = {
username:"rypy" }
console.log( username) ;
let {
log} = console; //从封装的对象中解构方法
log( "aaaa" ) ; //相当于console.log( "aaaa" ) ;
let obj = {
} ;
let arr = [ ] ;
( {
foo:obj.prop, bar:arr[ 0] } = {
foo:123, bar:true } ) ;
console.log( obj) ; //{
prop:123}
console.log( arr) ; //[ true]
//数组可以转换为对象{
0:true,1:false}
//字符串可以转换为数组[ a,b,c]
( {
} = [ true, false] ) ;
( {
} = 'abc' ) ;
( {
} = [ ] ) ;
for( let item of "我是憨憨" ) {
console.log( item) ;
}
function f( {
x,y} = {
x:0,y:0} ) {
console.log( x) ;
console.log( y) ;
}
f( {
x:3,y:8} ) ; //3,8
f( {
x:3} ) ; //3,undefined//{
x:3,y:undefined}
f( {
} ) ; //undefined,undefined
function f( {
x= 0,y= 0} = {
} ) {
console.log( x) ;
console.log( y) ;
}
f( {
x:3,y:8} ) ; //3,8
f( {
x:3} ) ; //3,0//{
x:3,y:undefined}
f( {
} ) ; //0,0
let str= "我是web憨憨" ;
let [ a,b,c] = str;
console.log( a) ; //我
console.log( b) ; //是
console.log( c) ; //w
let {
a:a,b:b,c:c} = str;
let {
0:a,1:b,2:c} = str;
console.log( a) ; //undefined
console.log( b) ; //undefined
console.log( c) ; //undefined
let {
length:len} = str;
console.log( length) ; //报错
console.log( len) ;
ES6
解构赋值的作用
交换变量的值 (先将对应的值给了等号后面的)
获取函数返回的部分值
函数参数的部分解构赋值
提取JSON格式的数据
提取对象中的方法
//1、值的交换
let a= 1;
let c= 5;
let e= 6;
let f= 9;
let b= 2;
// c= a; a= b; b= c;
[ a,b,c,e,f] = [ f,a,b,a,c] ; //[ 9,1,2,1,5]
console.log( a,b,c,e,f) ; //9,1,2,1,5
//2、获取函数返回值的部分内容
function f( ) {
// return [ 2,3,4,5,6,7] ;
// return {
username:"rypy" ,pwd:123456,sex:"男" }
return{
username:"rypy" ,pwd:123456,sex:"男" ,interest:{
read:true,write:false} }
}
let {
interest:{
write} ,pwd} = f( ) ;
console.log( write) ;
console.log( pwd) ;
let {
sex} = f( ) ;
console.log( sex) ;
let [ ,x,,,y] = f( ) ;
console.log( x,y) ;
//3、函数参数的部分解构赋值。
function f( x,y,z) {
if( x!= = undefined&& y!= = undefined&& z!= = undefined) {
return x+y+z;
} else if( x!= = undefined&& y!= = undefined) {
return x+y;
} else if( y!= = undefined&& z!= = undefined) {
return y+z;
} else if( x!= = undefined&& z!= = undefined) {
return x+z;
}
}
console.log( f( 1,3)) ;
console.log( f( 1,7)) ;
//4、提取JSON格式的数据
//5、提取对象中的方法
let {
entries} = Object; //Object.entries( )
let user= {
username:"rypy" ,pwd:123,sex:"男" } ;
for( let item of entries( user)) {
console.log( item) ;
}
模板字符串
模板字符串的关键词 :字符串或标签
反引号 $ {输出的变量名};
模板字符串中的字符类型 必须要放到反引号内 ;${},用来输出变量 的
模板字符串的作用
支持HTML标签的书写 (可以嵌套标签,并且直接输出变量,自动接受回车换行)
可以直接输出对象的属性或变量的值
支持js的判断输出 (三目和判断语句)
可以在${}内 直接使用函数的调用
面试题:++a与a++的区别?
面试题:== 和===的区别?
//模板字符串的关键词
// ` 字符串或标签` 反引号 ${输出的变量名} ;
let age= 20;
console.log( "我的年龄是" +age) ;
console.log( ` 我的年龄是${
age} ` ) ;
function f( ) {
return "憨憨你好!"
}
console.log( ` 你是谁?${
f( ) }