改变this指向
- 事件处理函数中this -> 事件源
- 普通函数中this -> window
- 定时器this -> window
- 自调用函数 this -> window
- 对象Object方法中this -> 当前对象-> 调用该方法的引用变量指向的对象
函数方法call方法
函数名.call(this指向的新对象,参数1,参数2...)
对象方法.call(this指向的新对象,参数1,参数2...)
var obj = {
name:'jack'
}
function fun(m,n){
console.log('m ',m, ' n ',n); //m 10 n 20
console.log('this -> ',this) // window -> obj this改变指向,指obj的name ‘jack’
}
fun.call(obj,10,20) //jack 10 20
var obj1 = {
name:'rose'
}
var obj = {
name:'jack',
say:function(){
console.log('this -> ',this) // 改变当前this(jack)指向 (rose) obj1
}
}
// obj.say()
obj.say.call(obj1)
apply方法
函数名.apply(this指向的新对象,[参数1,参数2...])
对象方法.apply(this指向的新对象,[参数1,参数2...])
var obj = {
name:'jack'
}
function fun(m,n){
console.log('m ',m, ' n ',n); //[10,20]
console.log('this -> ',this) // window -> obj this改变指向,指obj的name ‘jack’
}
fun.apply(obj,[10,20])
bind方法
var 新函数 = 函数名.bind(this指向的新对象)
var 新函数 = 对象方法.bind(this指向的新对象)
新函数(,参数1,参数2...)
var obj = {
name:'jack'
}
function fun(m,n){
console.log('m ',m, ' n ',n); //10,20
console.log('this -> ',this) // window -> obj this改变指向,指obj的name ‘jack’
}
var newFun = fun.bind(obj)
newFun(10,20)
充电宝案例
var jackObj = {
name: 'jack', //姓名
phoneBattery: 70, //手机电池电量70%
// 给手机电池充电
change: function (batteryNum) {
this.phoneBattery = batteryNum
},
}
var roseObj = {
name:'rose', //姓名
phoneBattery:10, //电池电量10%
}
// rose想借用jack的充电宝充电? 实际就是使用jackobj对象的chanage方法
console.log('rose充电前电量 ',roseObj.phoneBattery);
jackObj.change.call(roseObj,80) //改变this指向 指给rose
console.log('rose充电后电池电量 ',roseObj.phoneBattery);
jackObj.change(90) //jack的电量变为90
console.log(jackObj.phoneBattery);
ES6新特性
let 和 const 关键字
声明变量
- var num
- let num
- const num
区别
let 和 var[面试]
- let没有变量提升(预解析) let声明必须先定义再使用
console.log(num) //var可以先使用后声明 因为有预解析
var num = 300
- let不能重复声明变量
var num = 100 var num = 200 //后者覆盖前者
- let具有块作用域 (定义的值只能在块作用域使用)
//全局作用域 -> 局部作用域 -> 块作用域
let 和 const
- const声明的变量称为常量,只能赋值一次
应用场景
- 考虑兼容问题:使用var
- 不考虑兼容,变量可以多次改变值:let
- 变量值赋值一次后不再改变:const
箭头函数
作用
简化匿名函数的书写
语法
()=>{} <= function(){}
var fun = function(){ //匿名函数
console.log('hello')
}
fun()
var fun1 = ()=>{ //简化后
console.log('hello')
}
fun1()
ele.addEventListener('click',()=>{ 函数体})
简写
- 形参只有一个,括号可以省略: (m)=>{ } m => { }
- 函数体只有一行代码,大括号省略 : ()=>console.log('>>>')
- 只有一行代码,并且代码是return语句,大括号和return都可以省略 ()=>100
const f2 = () => 100
箭头函数this指向问题
在事件处理函数中 this->事件源
箭头函数中this指向 应用this所在的上下文环境中this对象
<button>按钮</button>
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
console.log('this -> ', this) // 事件源btn 上文
// 对象方法中this所在的上下文环境 是 事件处理函数中
const obj = {
name: 'jack',
say: ()=>{
console.log('obj this -> ', this) // this 为上下文中的this所指向的事件源btn
},
}
//下文
obj.say()
})
函数传递参数的时候的默认值
ES5实现方法
m =m || 100
function fn(m) {
m = m || 100
console.log('m ', m)
}
fn(200)
ES6实现方式
function fun(m = 100){}
function fun(m = 100) { // m = 200
console.log('m :', m)
}
fun(200)
解构赋值
快速从对象或者数组中取出成员的一个语法方式
对象
- let { 对象属性名1,对象属性名2 } = 对象名
- 注:大括号中变量名必须与对象属性名相同
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) //name:jack age:18
数组
- let [ 数组属性名1,数组属性名2 ] = 数组名
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) //a:1 b:2 c:3 } test2()
模板字符串
let str = `helloworld-${变量}`
展开运算符
语法
- 数组: ...数组名
- 对象: ...对象名
作用:
- 数组合并
- 对象属性合并
function test1(){ let arr = [1,2,3] // console.log(...arr) let arr2 = [4,5] let arr3 = [...arr,...arr2] // [1,2,3,4,5] let arr3 = arr.concat(arr2) // [1,2,3,4,5] console.log('arr3 ',arr3); // [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()
对象字面量简写
对象属性名和值变量名相同时,只写一个
let name = 'jane'
let age = 28
// let obj = {
// 对象属性名 name:name, 变量名
// 对象属性名 age:age 变量名
// }
let obj = { name, age }
console.log(obj) // {name: 'jane', age: 18}
案例购物车2.0
<div class="containter">
<!--==== logo区域===== -->
<div class="logo">
<img src="./image/dd_logo.jpg" alt="logo" />
</div>
<!--==== 购物车列表区域==== -->
<table>
<!-- 动态渲染 -->
</table>
<!-- 所有商品总价 -->
<div>
<h2>总价:¥0</h2>
</div>
<!-- 商品表单 -->
<div class="prowraper">
<form>
<input type="text" name="name" placeholder="请输入商品名"><br/>
<input type="text" name="price" placeholder="请输入商品价格"> <br/>
<input type="text" name="num" placeholder="请输入商品数量"> <br/>
<input type="text" name="url" placeholder="请输入商品图片地址"> <br/>
<input type="submit" id="confirm" value="添加商品">
</form>
</div>
</div>
<script src="./js/index.js"></script>
// 商品列表
let productList = [
{ number: 1001, name: 'javascript高级编程', url: './image/shoppingBg_03.jpg', price: 88.98, num: 0 },
{ number: 1002, name: 'css高级编程', url: './image/shoppingBg_06.jpg', price: 58.58, num: 0 },
{ number: 1003, name: 'html高级编程', url: './image/shoppingBg_03.jpg', price: 48.58, num: 0 },
]
const tableEle = document.querySelector('table')
/*
* 显示商品列表
*/
function showProductList() {
let str = `<tr>
<th>序列号</th>
<th>商品图片</th>
<th>商品信息</th>
<th>单价</th>
<th>数量</th>
<th width="100px">总价</th>
<th>操作</th>
</tr>`
let trArr = productList.map(item => {
return `<tr>
<td>${item.number}</td>
<td><img src="${item.url}" alt="图片1" /></td>
<td>${item.name}</td>
<td>¥${item.price}</td>
<td>
<input type="button" value="-" name="minus" /><input type="text" value="${
item.num
}" name="amount"/><input
type="button"
value="+"
name="plus"
/>
</td>
<td>¥${item.price * item.num}</td>
<td>移入收藏<br />删除</td>
</tr>`
})
str = str + trArr.join('')
tableEle.innerHTML = str
}
/**
* 绑定添加商品事件
*/
function bindAddProduct() {
const formEle = document.querySelector('form')
const nameInput = document.querySelector('input[name="name"]')
const priceInput = document.querySelector('input[name="price"]')
const numInput = document.querySelector('input[name="num"]')
const urlInput = document.querySelector('input[name="url"]')
formEle.addEventListener('submit', function (e) {
e = e || window.event
e.preventDefault() // 阻止默认行为
let name = nameInput.value // 商品名称
let price = priceInput.value // 商品价格
let num = numInput.value // 商品数量
let url = urlInput.value // 商品地址
addProduct(name, price, num, url)
// 清空表单数据
nameInput.value = ''
priceInput.value = ''
numInput.value = ''
urlInput.value = ''
})
}
/**
* 添加商品
* 1. 构造商品对象
* let product = { number: 1004, name: 'vue高级编程', url: './image/shoppingBg_03.jpg', price: 108.58, num: 0 }
* 2. 添加商品到商品数组
* productList.push(product)
*/
function addProduct(name, price, num, url) {
let number = getRandom(1000, 10000) // 随机生成4位商品序号
// 1. 构造商品对象
let product = {
number,
name,
url,
price,
num,
}
productList.push(product) // 2. 添加商品到商品数组
showProductList() // 3. 重新加载商品数组
}
/*
* 返回m到n之间的随机数
*/
function getRandom(x, y) {
var n = Math.max(x, y)
var m = Math.min(x, y)
return Math.floor(Math.random() * (n - m) + m)
}
showProductList()
bindAddProduct()
* {
padding: 0;
margin: 0;
}
.containter {
width: 1200px;
margin: 100px auto;
}
.containter table{
width: 100%;
}
.containter tr {
line-height: 40px;
text-align: center;
}
.containter tr,
th,
td {
border-bottom: 1px dotted gray;
}
.containter tr input {
width: 20px;
text-align: center;
}
.containter h2{
font-size: 18px;
text-align: right;
}
.containter table img{
width: 80px;
height: 100px;
}
/* 添加商品表单 */
.prowraper{
width: 600px;
margin: 20px auto;
border: 1px solid gray;
}
.prowraper form{
width: 100%;
padding: 20px;
}
.prowraper form input{
margin-top: 10px;
width: 90%;
line-height: 30px;
}
.prowraper form #confirm{
margin-top: 10px;
width: 200px;
height: 40px;
text-align: center;
line-height: 40px;
}