黑马程序员前端JavaScript入门到精通全套视频教程,javascript核心进阶ES6语法、API、js高级等基础知识和实战教程
// 一个 pink 对象
const pink = {
name: 'pink老师',
age: 18
}
const red = pink
console.log(red) // { name: 'pink老师', age: 18 }
red.name = 'red老师'
console.log(red) // { name: 'red老师', age: 18 }
// 但是 pink 对象里面的 name 值也发生了变化
console.log(pink) // { name: 'red老师', age: 18 }
const obj = {
uname: 'pink'
}
const o = { ...obj }
console.log(o) // { uname: 'pink' }
o.uname = 'red'
console.log(o) // { uname: 'red' }
console.log(obj) // { uname: 'pink' }
// 一个 pink 对象
const pink = {
name: 'pink老师',
age: 18
}
const red = {}
Object.assign(red, pink)
console.log(red) // { name: 'pink老师', age: 18 }
red.name = 'red老师'
console.log(red) // { name: 'red老师', age: 18 }
// 不会影响 pink 对象
console.log(pink) // { name: 'pink老师', age: 18 }
- 如果是简单数据类型拷贝值,引用数据类型拷贝的是地址 (简单理解:如果是单层对象,没问题,如果有多层就有问题)
let num = 1
// fn 就是递归函数
function fn() {
console.log('我要打印6次')
if(num >= 6) {
return
}
num++
fn() // 函数内部调用函数自己
}
fn()
function getTime() {
const time = new Date().toLocalString()
console.log(time)
setTimeout(getTime, 1000) // 定时器调用当前函数
}
getTime()
const o = {}
function deepCopy(newObj, oldObj) {
for(let k in oldObj) {
if(oldObj[k] instanceof Array) {
newObj[k] = []
deepCopy(newObj[k], oldObj[k])
}
else if(oldObj[k] instanceof Object) {
newObj[k] = {}
deepCopy(newObj[k], oldObj[k])
}
else {
newObj[k] = oldObj[k]
}
}
}
const obj = {
uname: 'pink',
age: 18,
hobby: ['篮球', '足球'],
family: {
baby: '小pink'
}
}
// 语法:_.cloneDeep(要被克隆的对象)
const o = _.cloneDeep(obj)
console.log(o)
o.family.baby = '老pink'
console.log(obj)
const obj = {
uname: 'pink',
age: 18,
hobby: ['篮球', '足球'],
family: {
baby: '小pink'
}
}
const o = JSON.parse(JSON.stringify(obj))
console.log(o)
o.family.baby = '老pink'
console.log(obj)
function counter(x, y) {
if(!x || !y) {
// throw '参数不能为空!';
throw new Error('参数不能为空!')
}
return x + y
}
counter()
function foo() {
try {
// 查找 DOM 节点
const p = document.querySelectro('.p')
p.style.color = 'red'
} catch(error) {
// try 代码段中执行有错误时,会执行 catch 代码段
// 查看错误信息
console.log(error.message)
// 终止代码继续执行
return
}
finally {
alert('执行')
}
console.log('如果出现错误,我的语句不会执行')
}
foo()
const arr = [1, 3, 5]
const newArr = arr.map((item, index) => {
debugger
console.log(item) // 当前元素
console.log(index) // 当前元素索引号
return item + 10 // 让当前元素 + 10
})
console.log(newArr) // [11, 13, 15]
// 普通函数
function sayHi() {
console.log(this)
}
// 函数表达式
const sayHello = function() {
console.log(this)
}
// 函数的调用方式决定了 this 的值
sayHi() // window
windows.sayHi()
// 普通对象
const user = {
name: '小明',
walk: function() {
console.log(this)
}
}
// 动态为 user 添加方法
user.sayHi = sayHi
user.sayHello = sayHello
// 函数的调用方式决定了 this 的值
user.sayHi()
user.sayHello()
<script>
'use strict'
function fn() {
console.log(this) // undefined
}
fn()
script>
console.log(this) // 此处为 window
// 箭头函数
const sayHi = function() {
console.log(this) // 该箭头函数中的 this 为函数声明环境中 this 一致
}
// 普通对象
const user = {
name: '小明',
// 该箭头函数中的 this 为函数声明环境中 this 一致
walk: () => {
console.log(this)
}
}
// DOM 节点
const btn = document.querySelector('.btn')
// 箭头函数,此时 this 指向了 window
btn.addEventListener('click', () => {
console.log(this)
})
// 普通函数,此时 this 指向了 DOM 对象
btn.addEventListener('click', function () {
console.log(this)
})
function Person() {
}
// 原型对象上添加了箭头函数
Person.prototype.walk = () => {
console.log('人都要走路...')
console.log(this); // window
}
const p1 = new Person()
p1.walk()
fun.call(thisArg, arg1, arg2, ...)
const obj = {
name: 'pink'
}
function fn() {
console.log(this) // 指向 obj {name: 'pink'}
}
fn.call(obj)
const obj = {
name: 'pink'
}
function fn(x, y) {
console.log(this) // 指向 obj {name: 'pink'}
console.log(x + y) // 传递过来的参数相加
}
fn.call(obj, 1, 2)
fun.apply(thisArg, [argsArray])
// 求和函数
function counter(x, y) {
return x + y
}
// 调用 counter 函数,并传入参数
let result = counter.apply(null, [5, 10])
console.log(result)
// 求数组最大值
const arr = [3, 5, 2, 9]
console.log(Math.max.apply(null, arr)) // 9,利用apply
console.log(Math.max(...arr)) // 9,利用展开运算符
fun.bind(thisArg, arg1, arg2, ...)
// 普通函数
function sayHi() {
console.log(this)
}
let user = {
name: '小明',
age: 18
}
// 调用 bind 指定 this 的值
let sayHello = sayHi.bind(user);
// 调用使用 bind 创建的新函数
sayHello()
const box = document.querySelector('.box')
let i = 1
function mouseMove() {
box.innerHTML = i++
}
function debounce(fn, t = 500) {
let timeId
return function () {
// 如果有定时器,先清除
if(timeId)
clearTimeout(timeId)
// 开启定时器
timeId = setTimeout(function() {
fn()
}, t)
}
}
box.addEventListener('mousemove', debounce(mouseMove, 500))
所谓节流(throttle),就是指连续触发事件但是在 n 秒中只执行一次函数
现实例子:只有等到了上一个人做完核酸,整个动作完成了,第二个人才能排队跟上
开发使用场景:小米轮播图点击效果、鼠标移动、页面尺寸缩放resize、滚动条滚动 就可以加节流
利用节流来处理-鼠标滑过盒子显示文字:
const box = document.querySelector('.box')
let i = 1
function mouseMove() {
box.innerHTML = i++
// 如果存在开销较大操作,大量数据处理,大量dom操作,可能会卡
}
function throttle(fn, t = 500) {
let startTime = 0
return function () {
let now = Date.now()
if(now - startTime >= t) {
fn()
startTime = now
}
}
}
box.addEventListener('mousemove', throttle(mouseMove, 500))
节流和防抖的区别是?
节流和防抖的使用场景是?
节流
const box = document.querySelector('.box')
let i = 1
function mouseMove() {
box.innerHTML = i++
// 如果存在开销较大操作,大量数据处理,大量dom操作,可能会卡
}
box.addEventListener('mousemove', _.throttle(mouseMove, 1000))
防抖
const box = document.querySelector('.box')
let i = 1
function mouseMove() {
box.innerHTML = i++
// 如果存在开销较大操作,大量数据处理,大量dom操作,可能会卡
}
box.addEventListener('mousemove', _.debounce(mouseMove, 1000))
页面打开,可以记录上一次的视频播放位置
const video = document.querySelector('video')
video.ontimeupdate = _.throttle(() => {
localStorage.setItem('currentTime', video.currentTime)
}, 1000)
video.onloadeeddata = () => {
video.currentTime = local.getItem('currentTime') || 0
}