改变this指向
1. 函数方法 call方法
语法:函数名.call(要改变的this指向,函数参数1,参数2....)
对象方法.call(this指向的新对象,参数1,参数2...)
2. apply 方法
函数名.apply(this指向新对象,[参数1,参数2…])
对象方法.apply(this指向新对象,[参数1,参数2…])
<script>
var obj={
name:'jack'
}
function fun(m,n){
console.log('m',m,'n',n);
console.log(this);//window->obj
}
fun.apply(obj,[10,20])
</script>
bind方法
var 新函数 = 函数名.bind(this指向新对象)
var 新函数 = 对象方法.bind(this指向新对象)
新函数(参数1,参数2)
示例一
<script>
var obj1 = {
name:'rose'
}
var obj = {
name:'jack',
say:function(){
console.log('this -> ',this) // 改变当前this(jack)指向 (rose) obj1
}
}
// obj.say()
obj.say.call(obj1) //对象方法也叫函数名
案例—充电宝
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>充电宝示例</title>
</head>
<body>
<script>
const jackObj = {
name: 'jack', //姓名
phoneBattery: 70, //手机电池电量70%
// 给手机电池充电
change: function (batteryNum) {
this.phoneBattery = batteryNum
},
}
const roseObj = {
name:'rose', //姓名
phoneBattery:10, //电池电量10%
}
// rose想借用jack的充电宝充电? 实际就是使用jackobj对象的chanage方法
console.log('rose充电前电量 ',roseObj.phoneBattery);
jackObj.change.call(roseObj,80)
console.log('rose充电后电池电量 ',roseObj.phoneBattery);
// jackObj.change(90)
// console.log(jackObj.phoneBattery);
</script>
</body>
</html>
ES6新特性
ES6可以统称2015年后javascript所有最新版本
let 和 const 关键字 用于声明变量(面试题)
区别:
let 和 var
- let没有变量提升(预解析) let声明变必须先定义再使用
console.log(num)
var num = 100 - let声明的变量,不能重复声明变量
var num = 100
var num = 200 - let具块作用域
全局作用域
局部作用域
块作用域 let
if(){ 中括号里的就是块级作用域,出了中括号就无法访问}
**let 和 const **
const声明的变量称为常量,只能赋值一次,声明时必须赋值
let声明可以不赋值
const num = 100
num = 200 x报错
兼容
1.考虑兼容问题
使用var
2. 变量可以多次改变值
let
3. 变量只赋值一次后,不再改变
const
const button = document.quererySelctor(‘button’) 如获取节点,一般都是不变的
声明函数也可以用const
箭头函数
-
箭头函数是 ES6 里面一个简写函数的语法方式
-
重点: 箭头函数只能简写函数表达式,不能简写声明式函数
-
语法: (函数的行参) => { 函数体内要执行的代码 }
-
形参只有一个, 括号可以省略
(m)=>{ } == m => { } -
函数体只有一行代码 大括号省略
() => {console.log(‘>>>’)} === () => console.log(‘>>>’) -
只有一行代码,并且代码是return语句,大括号和return都可省略
()=> {return 100} === () => 100
箭头函数的this指向问题
- 在事件处理函数中this->事件源
- 箭头函数中this指向 应用上下文中this对象 参照上下文环境this对象指向
应用上下文this对象
此时上下区域都是window对象
此时上下文环境是window对象
btn.addEventListener('click', function () {
console.log('this -> ', this) // 事件源btn
// 对象方法中this所在的上下文环境 是 btn
const obj = {
name: 'jack',
say: ()=>{
console.log('obj this -> ', this) // 对象方法中this->上下文环境 btn
},
}
obj.say()
})
案例–this指向
<script>
<!--
(function(形参){
//函数体
})(实参)
cb = function(){
console.log(this.len)
}
-->
var len = 117
let func = {
len: 935,
showLen: function () {
console.log(this.len) // 自调用函数中this->window 117;
},
show: function () {
let obj = this;
(function (cb) { //自调函数
//函数体
cb() //调用函数showLen
})(this.showLen) //实参this.showLen==func.showLen
},
}
func.show()
//拿到 len=935
<script>
var len = 117
let func = {
len: 935,
showLen: function () {
console.log(this.len) //935
},
show: function () {
let obj = this; //func
(function (cb) {
cb.call(obj) //改变自调函数的指向,改为func
})(this.showLen)
},
}
// func.showLen()
func.show()
函数传递参数的时候的默认值
就是当我不传递参数的时候,使用默认值,传递参数了就使用传递的参数
解构赋值
解构对象
就是快速的从对象或者数组中取出成员的一个语法方式
let { name, age } = obj 注: 大括号中变量名必须与对象属性名相同
解构数组
- 注意
交换变量
模板字符串和展开运算符
模板字符串
-
- ES5 中我们表示字符串的时候使用 ‘’ 或者 “”
-
- 在 ES6 中,我们还有一个东西可以表示字符串,就是 ``(反引号)
- 反引号可以直接在字符串里面拼接变量 ·hello${num}world·
展开运算符
-
- ES6 里面号新添加了一个运算符 … ,叫做展开运算符
-
- 作用是把数组展开
- 合并数组的时候可以使用
- 可以合并对象使用
- 在函数传递参数的时候也可以使用
对象字面量简化写法
当属性与值的变量同名时。可以只写一个
Symbol 类型–ES6新增基本数据类型
语法:let sym = Symbol(描述符) 描述符—提供当前symbol表示的含义
作用:保证每个属性的名字都是独一无二,避免冲突
注意,Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。
Set 复杂数据类型
- 作用 :存储无序数据集合
- 创建
let set =new Set() //空集合
let set = new Set([1,2,{name:'jack'},function(){}]) //可以存任一类型
-
属性与方法
- size 获取集合中数据数 - add 向集合追加数据 - delete 删除集合中数据 - clear 清空集合中所有元素 - forEach 遍历集合数据 - 集合转数组 ![在这里插入图片描述](https://img-blog.csdnimg.cn/bcb468a1a4874d0a98d633d30dcc0e31.png)
-
集合set转数组Array
let set = new Set([10,20,30])
console.log(set);//{10, 20, 30}
let arr = [...set]
console.log(arr) //[10, 20, 30]
console.log(arr[0]) //10
- 特点 集合set中元素不能重复,以一个为准
- 应用
数组去重
let arr=[11,32,43,21,11,32,43]
let set = new Set(arr)
arr=[...set] //两句结合成一句arr = [..new Set(arr)]
//代码越少,出错越低
console.log(arr)
以前写法:indexOf + includes 定义一个新数组,存储不重复元素,遍历原数组,判断新数组是否存在原数组元素,不存在加入新数组。
或者 双重for + splice
Map 复杂数据类型
-
作用:是一个数据集合,是一个很类似于对象Object的数据集合
- Map存储的数据也是key/value形式, key可以是任意类型,数字字符串都可 -
创建:
let map = new Map()
let map = new Map([ [‘name’,‘jack’], [{name:‘啊啊’},{value:11}], [100,18],[true,'成立 ']]) 一个key/value值用[ ]括起来
注:每一项必须用 [ ] 隔开,let map = new Map([[key,value],[{key},{value}],[key,value] ]) 逗号前就是key,逗号后是value -
key/value形式 :
let map = new Map([ [‘name’,‘jack’], [{name:‘啊啊’},{value:11}], [100,18],[true,'成立 ']]) -
属性和方法
- size 获取集合中数据数
- set 向集合追加数据
- delete 删除集合中数据
- clear 清空集合中所有元素
- get 用来获取该数据集合中的某一个数据
- has 用来判断数据集合中是否存在某一个数据 -
特点: 查找存储在map中的数据,可以不用遍历,根据key值直接获取
value = map.get(key)
//找到16对应的name
<script>
let arr=([
{name:'啊啊',value:11},
{name:'啊',value:61},
])
let map = new Map()
arr.forEach(item=>{
map.set(item.value,item.name) //遍历数组,转变为map类型
})
map.set(true,'成立')
map.set('name','jack')
map.set({name:'啊啊'},{value:11})
console.log(map);
console.log(map.get(61)); //啊
let map1 = new Map([ ['name','jack'], [{name:'啊啊'},{value:11}], [100,18],[true,'成立 ']])
console.log(map1);
</script>
let map = new Map([
['name', 'jack'],
[100, 18],
])
console.log(map.size)
//添加元素
map.set(true, '成立')
//获取元素
console.log(map.get('name'))
//删除元素
map.delete('name')
//清除所有元素
map.clear()
//判断集合是否有数据
let isHas = map.has('name')
}
for …of
- 作用:
可以用来遍历 数组, 字符串, Map
遍历对象 for-in - 语法:
for(let v of arr){ v表示:数组元素 }
for(let v of arr){
//遍历数组 v表示:数组元素
console.log(v)
}
for(let v of str){
console.log(v)
//遍历字符串 v表示:字符串元素
}
let arr = [10, 20, 30, 40]
for (const v of arr) {
console.log(v)
}
let str = 'hello'
for (const v of str) {
console.log(v)
}
let map=new Map([['姓名','小红'],['年龄','17']])
for (const v of map){
console.log(v)
}
//以前:
//遍历对象
for in eg: for(let key in obj) { console.log(key,obj[key])}
遍历数组,字符串, Map
let map = new Map([['hello','aaa'],])
模块化编程
前端模块化开发中:一个js文件就是一个模块,在js文件模块中定义的数据是私有的, 可以向外部暴露数据和方法,其它js文件模块可以引入暴露的方法数据进行使用。
- 模块化语法 import / export
- 模块化:
- 每个js文件都可以看作一个模块 xx.js
- 每个js模块中的内容与其它模块相互独立,变量相同也互不影响
- 模块间通讯
a.js 暴露模块
直接在要暴露的方法和变量名前面加 export 或者 export {变量 , 方法名} 如:export const getMax = function(m,n){ }
b.js 引入模块
import {变量,方法} from ‘./a.js’
或者index.html里引入
//a.js
let num = 100
//直接在需要暴露的方法前加export
export const getMax = function(m,n){
let max = m
if(n>max){
max=n
}
return max
//export {getMax,num}
}
//b.js
const getSum = function(){
return 100
}
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>最大值是><span></span></p>
<script type="module"> //表示下面使用的是模块化语法
import {getMax} from './a.js' //引入a.js模块的getMax方法
let max= getMax(209,30)
//显示最大值
const spanEle=document.querySelector('span')
spanEle.innerHTML = max
</script>
</body>
</html>
- 另一种暴露方式–export default–模块指定默认输出,
- 一个js只能使用一次
//c.js
export default {
name:'jack',
age:18
} //暴露对象、函数
//export default function(){}
//index.html
<script type="module">
import jackObj from './c.js' //引入名字可以自定义
console.log('jackObj',jackObj);
</script>
js错误处理机制
javascript引擎负责执行javascript代码,
如果发现错误代码,抛出异常错误, 如果异常错误没有处理语句,继续向上抛,直到系统处理
系统处理方式: 终止程序执行,错误语句下面的语句将不执行,在控制显示异常错误信息
异常错误类型
Error实例对象是最一般的错误类型,在它的基础上,JavaScript 还定义了其他6种错误对象。也就是说,存在Error的6个派生对象。
- SyntaxError 对象 --语法错误
- ReferenceError 对象–引用一个不存在的变量时发生的错误
console.log(a) Uncaught ReferenceError: a is not defined - TypeError 对象–是变量或参数不是预期类型时发生的错误
Uncaught TypeError: Cannot read property - RangeError 对象–超出有效范围时发生的错误
主要有几种情况,一是数组长度为负数,二是Number对象的方法参 数超出范围,以及函数堆栈超过最大值。
** - 自己捕获异常进行处理,有错误抛出错误,会继续执行下面代码
**
try{
// 可能发生异常的代码
}catch(error){
console.log(error) //error是错误信息
}
try {
const num = 100
num = 200
} catch (error) {
console.log('程序出错了 :')
} finally{
console.log('不论程序有无出错,都会执行')
}
finally 代码块
try…catch结构允许在最后添加一个finally代码块,表示不管是否出现错误,都必需在最后运行的语句。
作用:资源的回收