JavaScript - day2学习笔记

JavaScript - day2学习笔记

面向对象编程

构造函数与原型对象

使用构造函数创建对象,通过原型共享方法节约内存

// 构造函数 - 存在内存浪费问题
function Person(name) {
  this.name = name
  this.sayHi = function() {
    console.log('Hi ' + this.name)
  }
}

// 原型对象 - 共享方法节约内存
function Person(name) {
  this.name = name
}
Person.prototype.sayHi = function() {
  console.log('Hi~' + this.name)
}

const p1 = new Person('小明')
const p2 = new Person('小红')
p1.sayHi() // Hi~小明
p2.sayHi() // Hi~小红 - 共享同一个方法

原型链机制

基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对

象的链状结构关系称为原型链(对象属性查找的链式结构)
在这里插入图片描述

function Star() { }
Star.prototype.name = '原型上的名字'

const ldh = new Star()
console.log(ldh.name) // 查找顺序:ldh自身 → Star原型 → Object原型 → null

// instanceof 检测原型链
console.log(ldh instanceof Star) // true
console.log(ldh instanceof Object) // true

原型继承

通过原型实现对象间的继承关系

// 父类
function Person() {
  this.eyes = 2
  this.head = 1
}

// 子类继承
function Woman() {}
Woman.prototype = new Person()
Woman.prototype.constructor = Woman
Woman.prototype.baby = function() {
  console.log('生孩子')
}

function Man() {}
Man.prototype = new Person()
Man.prototype.constructor = Man

const red = new Woman()
console.log(red.eyes) // 2 - 继承自Person

深浅拷贝

浅拷贝

拷贝对象的第一层属性,引用类型共享地址

const obj = {
  name: '小明',
  hobby: ['篮球', '游泳'],
  info: {age: 18}
}

// 对象浅拷贝
const obj2 = Object.assign({}, obj)
const obj3 = {...obj}

// 数组浅拷贝
const arr = [1, 2, [3, 4]]
const arr2 = arr.concat()
const arr3 = [...arr]

obj2.hobby[0] = '足球'
console.log(obj.hobby[0]) // 足球 - 被影响,因为共享地址

深拷贝

完全拷贝对象,包括嵌套的引用类型

const obj = {
  name: '小明',
  hobby: ['篮球', '游泳'],
  info: {age: 18}
}

// 1. 递归实现深拷贝
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 o = {}
deepCopy(o, obj)

// 2. JSON序列化方式
const o2 = JSON.parse(JSON.stringify(obj))

// 3. 使用lodash库
const o3 = _.cloneDeep(obj)

o.hobby[0] = '足球'
console.log(obj.hobby[0]) // 篮球 - 不受影响

异常处理

throw抛出异常

主动抛出错误信息,终止程序执行

function counter(x, y) {
  if(!x || !y) {
    throw new Error('参数不能为空!')
  }
  return x + y
}

counter() // 抛出错误:参数不能为空!

try…catch捕获异常

捕获并处理代码执行中的错误

function foo() {
  try {
    // 可能出错的代码
    const p = document.querySelector('.p')
    p.style.color = 'red'
  } catch (error) {
    // 错误处理
    console.log('错误信息:', error.message)
    return // 终止执行
  } finally {
    console.log('无论是否出错都会执行')
  }
  console.log('没出错时执行')
}
foo()

debugger调试

在代码中设置断点进行调试

function calculate() {
  const a = 10
  debugger // 执行到此会暂停
  const b = 20
  return a + b
}
calculate()

this处理

普通函数this

this指向调用该函数的对象

function sayHi() {
  console.log(this)
}

const user = {
  name: '小明',
  sayHi: sayHi
}

sayHi() // window - 无明确调用者
user.sayHi() // user对象 - 调用者是user

箭头函数this

继承外层作用域的this,自身不绑定this

const user = {
  name: '小明',
  sayHi: function() {
    // 普通函数 - this指向调用者
    console.log('普通函数:', this.name)
    
    const arrowFn = () => {
      // 箭头函数 - 继承外层this
      console.log('箭头函数:', this.name)
    }
    arrowFn()
  }
}

user.sayHi()
// 普通函数: 小明
// 箭头函数: 小明

改变this指向(call,apply,bind)

动态控制函数中this的值

function introduce(age, hobby) {
  console.log(`我是${this.name}, ${age}岁, 喜欢${hobby}`)
}

const user = {name: '小明'}
const student = {name: '小红'}

// 1. call - 立即执行,参数逐个传递
introduce.call(user, 18, '篮球')

// 2. apply - 立即执行,参数数组传递
introduce.apply(student, [16, '唱歌'])

// 3. bind - 返回新函数,不立即执行
const boundFn = introduce.bind(user, 20, '游泳')
boundFn()

性能优化

防抖(debounce)

连续触发时只执行最后一次

function debounce(fn, delay) {
  let timer
  return function() {
    clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this, arguments)
    }, delay)
  }
}

// 使用示例
const searchInput = document.querySelector('.search')
searchInput.addEventListener('input', debounce(function(e) {
  console.log('搜索:', e.target.value)
}, 500))

节流(throttle)

连续触发时按固定频率执行

function throttle(fn, delay) {
  let flag = true
  return function() {
    if (!flag) return
    flag = false
    setTimeout(() => {
      fn.apply(this, arguments)
      flag = true
    }, delay)
  }
}

// 使用示例
window.addEventListener('scroll', throttle(function() {
  console.log('滚动位置:', window.scrollY)
}, 200))

视频播放进度保存(节流应用)

使用节流技术优化视频播放进度的实时保存,避免频繁操作

// 获取视频元素
const video = document.querySelector('video')

// 使用节流保存播放进度 - 每秒保存一次
video.ontimeupdate = _.throttle(() => {
  // 获取当前视频时间
  console.log('当前播放时间:', video.currentTime)
  
  // 把当前时间存储到本地存储
  localStorage.setItem('currentTime', video.currentTime)
}, 1000)

// 页面加载时恢复播放进度
video.onloadeddata = () => {
  // 从本地存储获取记录的时间,如果没有则从0开始
  const savedTime = localStorage.getItem('currentTime')
  video.currentTime = savedTime ? parseFloat(savedTime) : 0
  console.log('恢复播放位置:', video.currentTime)
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值