Javascript高阶_PINK笔记

解构赋值

是一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值

数组解构

将数组里的值批量赋值给变量

let a,b,c=[1,2,3]

对象解构

将对象的属性和方法快速批量赋值给一系列变量
注:

  • 对象属性的值将被赋值给与属性名相同的变量(属性名===变量名
  • 解构的变量名不要和外面的变量名冲突否则报错
  • 对象中找不到与变量名一致的属性时变量值为undefine
  // 1
  let {uname,age}={uname:'feng',age:18}
  // 2
  let user={
    address:'china',
    hobby:'dance'
  }
  let {address,hobby}=user
  //对象解构的变量名可更改 旧变量名:新变量名
  let {uname:username,age}={uname:'feng',age:18}
// 例子
const pig={name:'peiqii',age:16}
//const {name,age}=pig

const {name:uname,age}=pig
console.log(uname)
console.log(age)

// 数组对象
const goods=[
  {
    goodsName:'小米',
    price:199
  }
]
const [{goodsName,price}]=goods
console.log(goodsName)
console.log(price)

多级对象解构

const pig={
  uname:'sd',
  family:{
    mom:'mama',
    fa:'baba',
    sis:'jie'
  },
  age:6
}
const {uname,family:{mom,fa,sis},age}=pig
console.log(uname,mom,fa,sis,age);

forEach

遍历数组的每个元素,并将元素传递给回调函数
(只能遍历数组)
在这里插入图片描述

与map的区别

  • map返回一个新数组
  • foreach只遍历不返回数组

filter 筛选数组

创建一个新数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
使用场景:筛选数组符合条件的元素,并返回筛选之后元素的新数组
在这里插入图片描述

const arr=[10,20,30]
const newa=arr.filter(function(item,index){
     return item>=20
 })
console.log(newa);
 
// 简化
const newArr=arr.filter(item=>item>=20)
console.log(newArr);

创建对象的三种方式

  • 对象字面量
const obj={
	name:'明'
}
  • 利用 new Object 创建
const obj=new Object({uname:'pink})
  • 利用构造函数创建对象

构造函数

特殊的函数,主要用来初始化对象
使用场景:可通过构造函数来快速创建多个类似的对象

  • 约定
    • 命名以大写字母开头
    • 它只能由new来执行
function Pig(name,age,gender){
	this.name=name
	this.age=age
	this.gender=gender
}
// 创建对象
const peppa=new Pig('pepp',6,'女')
const dad=new Pig('pdad',27,'男')
const mum=new Pig('pmom',24,'女')

说明:
在这里插入图片描述

new实例化执行过程

1、创建新的空对象
2、构造函数this指向新对象
3、执行构造函数代码,修改this,添加新属性
4、返回新对象

实例成员和静态成员

通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员

  • 实例对象是相互独立

构造函数的属性和方法称为静态成员
注:

  • 静态成员只能构造函数来访问
  • 静态方法中的this指向构造函数
function Pig(uname,age){
 	this.uname=uname
    this.age=age
}
Pig.eyes=2
Pig.sayhi=function(){
    console.log(this);
}
Pig.sayhi()

内置构造函数

其实字符串、数值、布尔等基本类型也都有专门的构造函数,这些我们称为包装类型

 const str='pink'
 console.log(str.length)

 // js 底层完成,把简单数据类型包装为引用数据类型
 const str1=new String('pink')
  • 引用类型
    • Object
    • Array
    • RegExp
    • Date
  • 包装类型
    • String
    • Number
    • Boolean

Object

创建普通对象

常用的静态方法

  • Object.keys(对象)
const o={uname:'mini',age:18}
console.log(Object.keys(o));  // 返回为数组形式
console.log(Object.values(o));
  • Object.assign()
    对象的拷贝,经常用于给对象添加属性
const o={uname:'mini',age:18}
const obj={}
Object.assign(obj,o)
console.log(obj);

console.log(obj,{gender:'女'});

Array

  • 数组常见的实例方法(核心)
    在这里插入图片描述
// reduce实现数组求和
const arr=[1,5,8]

// 1\没有初始值
const total=arr.reduce(function(pre,current){
    return pre+current
})

// 2\有初始值
const total1=arr.reduce(function(pre,current){
    return pre+current
},10)

reduce过程:
1、若没有起始值,则上一次值以数组的第一个数组元素的值
2、每一次循环,把返回值给做为下一次循环的上一次值
3、若有起始值,则起始值作为上一次值

// 如果是数组对象,必须添加初始值
const arr1=[{
    name:'feng',
    salary:1000
},{
    name:'xiang',
    salary:1000
},{
    name:'duan',
    salary:1000
}]

const final=arr1.reduce(function(prev,current){
    console.log(prev,current);
    return prev+current.salary
},0)
console.log(final);
  • 数组其他方法
    在这里插入图片描述
// 小案例
// 获取所有属性,拼接成字符串
const spec={size:'40*40cm',color:'blank'}
const newA= Object.values(spec).join('/')
console.log(newA);

伪数组转化为真数组

  • 伪数组没有pop()方法

String

在这里插入图片描述
includes 区分是大小写的

Number

  • toFixed() 设置保留两位小数,四舍五入

编程思想

面向过程:分析解决问题的步骤,然后用函数一步一步实现,使用的时候一次一次调用
面向对象:把事务分解成一个个对象,然后由对象之间分工与合作。根据对象功能划分,而不是步骤
- 灵活、代码复用、易维护和开发

  • 特性
    • 封装性
    • 继承性
    • 多态性

构造函数

JS实现面向对象需通过构造函数实现
构造函数 存在浪费内存的问题

希望 所有对象使用一个函数

原型

是构造函数的一个对象。称prototype为原型对象

  • 构造函数通过原型分配的函数是所有对象所共享的
  • js规定,每一个构造函数都有一个prototype属性,指向另一个对象,所以我们也称为原型对象
  • 这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存
  • 我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法
  • 构造函数和原型对象中的this都指向实例化对象

公共的属性写在构造函数中
==公共的方法写在原型对象上 ==

  • 原型作用
    • 共享方法
    • 可以把那些不变的方法直接定义在prototype对象上
const arr=[1,2,3]
// 给数组扩展求最大值方法和求和方法

Array.prototype.max=function(){
    return Math.max(...this)
    // 原型函数中的this指向实例对象
}
console.log(arr.max());

constructor属性

  • 每个原型对象里面都有个constructor属性
  • 作用:指向该原型对象的构造函数

思考:为什么实例对象可以访问原型对象里面的属性和方法

对象原型

  • 对象都会有一个属性__proto__指向构造函数的prototype原型对象,之所以我们对象可以在使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型的存在
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
let that
function Person(name){
     this.name=name
 }
 Person.prototype.sing=function(){
     that=this
     console.log('sing');
 }
 const peppa=new Person('佩奇')
 peppa.sing()      
 console.log(peppa===that);   // 判断构造函数===原型对象
 console.log(peppa.__proto__===Person.prototype);  // 判断对象原型===原型对象

原型继承

JS中大多是借助原型对象实现继承的特性

  • 父构造函数(父类) 子构造函数(子类)
  • 子类的原型=new 父类

原型链

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

在这里插入图片描述
查找规则
在这里插入图片描述

浅拷贝

拷贝的是地址,适合单层简单数据类型,不适合复杂数据类型
常见方法:
1、拷贝对象:Object.assign()/展开运算符{…obj} 拷贝对象
2、拷贝数组:Array.prototype.concat() 或者 […arr]

let obj={
    uname:'niuniu',
    age:18
}
let o={...obj}  // 已经重新new了一个对象,不会改变原来obj的值
o.age=20
console.log(o);    //20
console.log(obj);    //18

const o={}
Object.assign(o,obj)
o.age=20
console.log(o);
console.log(obj);

注:

  • 直接赋值的方法,只要是对象,都会相互影响,因为是直接拷贝对象栈里面的地址

  • 浅拷贝如果是一层对象,不相互影响,如果出现多层对象拷贝会相互影响

  • 理解浅拷贝

    • 拷贝对象之后,里面的属性值是简单数据类型直接拷贝值
    • 如果属性值是引用数据类型则拷贝的是地址

深拷贝

拷贝的是对象,不是地址

常见方法:

  1. 通过递归实现深拷贝
// 拷贝函数
        function deepCopy(newObj,oldObj){
            for(let k in oldObj){
                if(oldObj[k] instanceof Array){
                    newObj[k]=[]
                    // newObj[k] 接受 []
                    // oldObj[k] ['dance','sing']
                    deepCopy(newObj[k],oldObj[k])
                }
                // 要先写Array再写Object,因为数组也属于对象
                else if(oldObj[k] instanceof Object){
                    newObj[k]={}
                    // newObj[k] 接受 []
                    // oldObj[k] ['dance','sing']
                    deepCopy(newObj[k],oldObj[k])
                }
                else{
                    newObj[k]=oldObj[k]
                }
                
            }
        }
  1. lodash/cloneDeep
<script src="./lodash.min.js"></script>
    <script>
        const obj={
            uname:'pink',
            age:18,
            hobby:['sing','dance'],
            family:{
                baby:'小pink'
            }
        }
        const o=_.cloneDeep(obj)
        o.family.baby='lao'
        console.log(o);

        console.log(obj);
    </script>
  1. 通过JSON.stringfy() 实现
        const obj={
            uname:'pink',
            age:18,
            hobby:['sing','dance'],
            family:{
                baby:'小pink'
            }
        }
        // 把对象转换为JSON字符串
        console.log(JSON.stringify(obj));
        // 再转换成对象时创建了一个新的对象,与原来无关,因此能实现深拷贝
        const o=JSON.parse(JSON.stringify(obj))
        o.family.baby='lao'
        console.log(o);
        console.log(obj);

函数递归:在函数内部可以调用其本身,那么这个函数就是递归函数

// 用setTimeout模拟setInterval,用递归方式实现
function getTime(){
     document.querySelector('div').innerHTML=new Date().toLocaleString()
     setTimeout(getTime,1000)     
 }
getTime()

异常处理

  • throw 抛异常
  • try/catch 捕获错误信息
  • debugger

处理this

this指向

  • 普通函数的调用方式决定了this的值,即【谁调用this指向谁】
  • 普通函数没有明确调用者时this值为window,严格模式下没有调用时this的值为undefine
  • 对象里面没有this,函数作用域中才有this

改变this指向

  • call()
    在这里插入图片描述
  const obj={
      uname:'pink',
      age:18
  }

  function fn(x,y){
      console.log(this);  //window
      console.log(x+y);
  }
  // 1\调用函数
  // 2\改变this指向
  fn().call(obj,1,2)
  • apply()
    在这里插入图片描述
//apply()
function fn(){
    console.log(this);
}
fn.apply(obj,[1,2])

// 使用场景:求数组最大值
// 1写法
//const max=Math.max(1,2,3)
//console.log(max);
// 2写法
const arr=[100,44,22]
const max=Math.max.apply(Math,arr)
const min=Math.min.apply(Math,arr)
// 3写法
console.log(Math.max(...arr));
  • bind()(!important)
    在这里插入图片描述

call 和apply的区别

  • 都是调用函数,都能改变this指向
  • 参数不一样,apply传递的必须是数组

call apply bind 总结

在这里插入图片描述

防抖

单位时间内,频繁触发事件,只执行最后一次
(多次触发,会取消上一次执行,重新计时,执行下一次的)

  • lodash库实现防抖-500毫秒后采取+1
    _.debounce(fun,时间)

  • 手写防抖函数(用定时器)
    在这里插入图片描述

节流

单位时间内,频繁触发事件,只执行一次
(500ms内,不管触发多少次事件,只执行一次)
使用场景:
高频事件:鼠标移动mousemove、页面尺寸缩放resize7滚动条滚动scroll

核心思路:
在这里插入图片描述

function throttle(fn,t){
      let timer=null
      return function(){
        if(!timer){
          timer=setTimeout(function(){
            fn()
            //清空定时器
            timer=null
            // setTimeout中无法删除定时器,因为定时器还在运作,所以使用timer=null 而不是clearTimeout(timer)
          })
        }
      }
    }
    box.addEventListener('mousemove',throttle(mouseMove,500))

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值