一、改变this指向
我们复习一下:
- 全局定义的函数直接调用this,this指向window
- 对象内部的方法调用,this指向调用者
- 定时器的处理函数调用,this指向window
- 事件处理函数,指向事件源
- 自调用函数,指向window
函数内部的 this 只和函数的调用方式有关系,和函数的定义方式没有关系。上面说的都是函数的基本调用方式里面的this指向,我们还有三个可以忽略函数本身的this指向转而指向别的地方,强行改变this指向的方法 -- call、apply、bind。
1.call:附加在函数调用后面使用,可以忽略函数本身的this指向
语法:函数名.call(this指向的新对象,参数1,参数2...)
对象方法.call(this指向的新对象,参数1,参数2...)
使用call方法时会立即执行函数,第一个参数是你要改变的函数内部的this指向,第二个参数开始,依次是向函数传递参数。
2.apply:附加在函数调用后面使用,可以忽略函数本身的this指向
语法:函数名.apply(this指向新对象,[参数])
对象方法.apply(this指向新对象,[参数1,参数2...])
使用apply方法时会立即执行函数,第一个参数是你要改变的函数内部的this指向,第二个参数是一个数组,数组里面的每一项依次是向函数传递参数。
3.bind:附加在函数调用后面使用,可以忽略函数本身的this指向。和前两个有些不一样,就是不会立即执行函数,而是返回一个已经改变了this指向的新的函数。
语法:var 新函数 = 函数名.bind(this指向新对象)
var 新函数 = 对象方法.bind(this指向新对象)
新函数(参数1,参数2)
<!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>改变this指向</title>
</head>
<body>
<button>按钮</button>
<script>
var obj = {
name:'jack'
}
var btn = document.querySelector('button')
btn.addEventListener('click',function(){
console.log('this -> ',this)
})
function fun(m,n){
console.log('m ',m, ' n ',n);
console.log('this -> ',this) // window -> obj
}
fun()
fun.call(obj,10,20)
fun.apply(obj,[10,20])
var newFun = fun.bind(obj)
newFun(10,20)
</script>
</body>
</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>充电宝</title>
</head>
<body>
<script>
var jackObj = {
name:'jack',
phoneBattery:70, //手机电池电量
//给手机充电
change:function(batteryNum){
this.phoneBattery = batteryNum
},
}
var roseObj = {
name:'rose',
phoneBattery:10,
}
//rose想借用Jack的充电宝充电
jackObj.change.call(roseObj,80)
console.log('充电后电量',roseObj.phoneBattery)
</script>
</body>
</html>
二、ES6新特性
JavaScript的标准——ECMAScript在不断发展,最新版ECMAScript 6标准(简称ES6)已经在2015年6月正式发布,ES6可以统称2015年后javascript所有最新版本。
1.let和const关键字
我们以前都是使用 var 关键字来声明变量的,在 ES6 的时候,多了两个关键字 let 和 const,也是用来声明变量的。
区别:
- let 和 const 不允许重复声明变量,const声明的变量称为常量,必须赋值,且只能赋值一次
- 没有变量提升(预解析)
-
let具有块作用域
应用场景:
1.考虑兼容问题,使用var
2. 变量可以多次改变值,使用let
3. 变量只赋值一次后,不再改变,使用const
2.箭头函数
作用:简化函数(匿名函数)的书写
语法:
()=>{}
function(){ }
简写:
1. 形参只有一个, 括号可以省略
(m)=>{} 可以写成 m => {}
2. 函数体只有一行代码 大括号省略
() => {console.log('>>>')}
() => console.log('>>>')
()=> {return 100}
3.只有一行代码,并且代码是return语句,大括号和return都可省略
() => 100
<!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>箭头函数</title>
</head>
<body>
<button>按钮</button>
<script>
const f1 = () => console.log('f1>>>>>')
const f2 = () => 100
let v = f2()
console.log('v ', v)
const getMax = m => {
let n = 45
var max = m
if (n > max) {
max = n
}
return max
}
let m = getMax(23)
console.log('m ', m)
const fun = function () {
console.log('fun>>>>')
}
const fun1 = () => {
//函数体
console.log('fun111>>>>')
}
// fun1()
const btn = document.querySelector('button')
btn.addEventListener('click', () => {
console.log('函数体代码')
})
const obj = {
name: 'jack',
say: () => {
console.log('say>>>>')
},
}
obj.say()
</script>
</body>
</html>
箭头函数this指向问题:
1.在事件处理函数中this->事件源
2.箭头函数中this指向 应用上下文中this对象
<!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>箭头函数this指向问题</title>
</head>
<body>
<button>按钮</button>
<script>
const btn = document.querySelector('button')
console.log('this -> ', this) // 应用上下文this对象
function test1() {
btn.addEventListener('click', () => {
console.log('this -> ', this)
})
const obj = {
name: 'jack',
say: () => {
console.log('obj this -> ', this)
},
}
obj.say()
}
btn.addEventListener('click', function () {
console.log('this -> ', this) // 事件源btn
// 对象方法中this所在的上下文环境 是 事件处理函数中
const obj = {
name: 'jack',
say: () => {
console.log('obj this -> ', this) // 对象方法中this->当前对象
},
}
obj.say()
})
</script>
</body>
</html>
函数传递参数时的默认值:
ES5--> m || m=100
ES6--> function fun(m = 100){ }
<!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>默认值</title>
</head>
<body>
<script>
function fn(m) {
m = m || 100
console.log('m ', m)
}
// fn(200)
function fun(m = 100) { // m = 200
console.log('m :', m)
}
fun(200)
</script>
</body>
</html>
3.解构赋值
解构赋值就是快速从对象或者数组中取出成员的一个语法方式。
let {name,age} = obj
let [a,b,c] = arr
注:大括号中变量名必须与对象属性名相同
<!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>解构赋值</title>
</head>
<body>
<script>
function test2() {
const arr = [1, 2, 3]
// let a = arr[0]
// let b = arr[1]
// let c = arr[2]
let [a, b, c] = arr // 数组解构赋值
console.log('a :', a, ' b :', b, ' c :', c)
}
test2()
function test1() {
const obj = {
name: 'jack',
age: 18,
score: 98,
num: 1001,
}
// let name = obj.name // jack
// let age = obj.age // age
let { name, age, score, num } = obj // 解构对象赋值 给大括号中变量name和age
console.log('name :', name, ' age :', age)
}
</script>
</body>
</html>
4.模板字符串
格式: `${}`
例:
let str = `helloworld-${变量}`
5.展开运算符
作用: 数组合并。
运用:...需展开的名字
<!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>展开运算符</title>
</head>
<body>
<script>
function test1(){
let arr = [1,2,3]
console.log(...arr)
let arr2 = [4,5]
let arr3 = [...arr,...arr2]
console.log(arr3) //Array(5) [ 1, 2, 3, 4, 5 ]
}
// test1()
function test2(){
let obj1 = {
name:'jack',
age:18
}
let obj2 = {
...obj1,
gender:'女'
}
console.log('obj2 ',obj2) // {name: 'jack', age: 18, gender: '女'}
}
test2()
</script>
</body>
</html>
6.对象字面量简写
对象属性名和值变量名相同的,只写一个.
<!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>字面量简写</title>
</head>
<body>
<script>
let name = 'Jane'
let age = 28
// let obj = {
// name:name,
// age:age
// }
let obj = { name, age }
console.log(obj) // {name: 'jane', age: 18}
</script>
</body>
</html>
三、购物车案例实现思路
购物车2.0目标:数据操作 - 实现数据和界面分离
+ 商品列表 showProductList()
+ 添加商品
- 添加商品表单界面 --> 动态获取商品数据
- 构造商品对象
- 添加商品对象到商品数组