windows对象及js高级使用

一.windows对象

1.1location对象

  • href:可以获取或者设置当前页面的url地址
  • search:可以获取url地址中的查询字符串 符号?后面部分
  • hash:可以获取url地址中的哈希值 符号#后面部分
  • reload:可以刷新当前页面(传入参数为true时强制刷新)

1.2navigator对象

1.3history对象

  • 前进:history.go(1) history.forward()
  • 后退:history.go(-1) history.back()

1.4本地存储

<body>

  <script>

    //本地存储locationStorage  (sessionStorage同理,略)

    localStorage.setItem('name','gzbn')

    console.log(localStorage.getItem('name'))

    localStorage.removeItem('name')

  

    //本地存储复杂数据类型

    const obj = {

      id: 1,

      uname:'gzbn',

      hobby:['吃饭','睡觉','玩游戏']

    }

   //需要将复杂数据类型转换成JSON字符串,再存储到本地

    localStorage.setItem('obj',JSON.stringify(obj))

    const objItem = localStorage.getItem('obj')

    console.log(objItem);

     //取出来的是字符串,不是对象,无法直接使用, 所以转化为字符串

    console.log(JSON.parse(objItem))  

  </script>

</body>

1.5.正则表达式

1.5.1语法

console.log(/哈/.test(‘哈’))

1.5.2元字符

  • 边界符(^ $)
  • 量词(表示重复次数)
  • 字符类([a-z] \d \s)
量词说明
+重复至少1次
?重复0次或1次
*重复0次或多次
{m,n}重复m到n次
字符类说明
\d或[0-9]0-9都可以
\D或[^0-9 ]除0-9外的所有字符
\w或[A-Za-z0-9_]匹配任意字母,数字,下划线
\s或[\t\r\n\v\f]匹配空格(包括换行符,制表符,空格符等)
.匹配除换行符之外的任何单个字符

1.5.3修饰符

  • i 是单词 ignore 的缩写,正则匹配时字母不区分大小写
  • g 是单词 global 的缩写,匹配所有满足正则表达式的结果
    replace替换:
    const str = '你是xx'

    console.log(str.replace(/xx/,'好人'));

二.作用域&函数进阶&解构

2.1作用域

2.1.1作用域:

局部作用域(函数作用域和块作用域)和全局作用域(script标签 和 .js 文件)

总结

  • let const声明的变量会产生块作用域,var不会产生块作用域
  • 推荐使用let/const

作用域链:会优先查找当前函数作用域中查找变量;查找不到则会依次逐级查找父级作用域直到全局作用域

2.1.2垃圾回收机制:

JS中内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收

内存泄漏:不再用到的内存,没有及时释放,就叫做内存泄漏

堆栈空间分配

  • 栈(操作系统): 由操作系统自动分配释放函数的参数值、局部变量等,基本数据类型放到栈里面
  • 堆(操作系统): 一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型放到堆里面

常见浏览器垃圾回收算法

  • 引用计数法:是看一个对象是否有指向它的引用,没有引用了就回收对象,每引用一次就+1,减少就-1,引用次数为0,则释放内存(遇到循环引用会导致内存泄漏)
  • 标记清除法:从根部扫描对象,能查找到的就是使用的,查找不到的就要回收

2.1.3闭包

闭包:内层函数 + 外层函数的变量

作用:封闭数据,实现数据私有,外部也可以访问函数内部的变量; 闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来

问题:可能引用内存泄漏

2.1.4变量提升

  • var字声明变量会有变量提升
  • 只提升变量声明, 不提升变量赋值

2.2函数进阶

2.2.1函数提升

函数表达式不存在提升的现象

    fn()

    function fn() {

      console.log(1)

    }

  

    fn1()

    var fn1 = function(){

      console.log(1)  //函数表达式不会提升

    }

2.2.2函数参数

  • 动态参数:arguments(伪数组,只存在于函数中) - 不确定函数参数个数时可使用
    function sum(){

      let s = 0

      for(let i = 0;i < arguments.length; i++){

        s += arguments[i]

      }

      console.log(s)

    }

    sum(2,3)   //5
  • 剩余参数:… 是语法符号,置于最末函数形参之前,用于获取多余的实参
    function getNum2(a,b,...arg){

      console.log(arg);//(2) [4, 5]

    }

    getNum2(2,3,4,5)

展开运算符:用于数组

    const arr1 = [1,2,3]

    const arr2 = [4,5]

    console.log(...arr1)// 1 2 3

    console.log(Math.max(...arr1)) //求最大值 3

    console.log(...arr1,...arr2) //合并数组 1 2 3 4 5

2.2.3箭头函数

箭头函数语法总结

  • 只有一个参数时可以省略圆括号()
  • 函数函数体只有一行代码时可以省略花括号{},并自动做为返回值
  • . 加括号的函数体返回对象字面量表达式
    箭头函数参数总结
  • 普通函数有arguments 动态参数
  • 箭头函数没有 arguments 动态参数,但是有 剩余参数 …args
    //箭头函数1:基本写法

    const fn1 = () => {

      console.log('箭头函数写法');

    }

    //箭头函数2:只有一个参数时

    const fn2 = x => {

      console.log('只有一个参数时,可省去()');

    }

    //箭头函数3:函数体只有一行时,可以写到一行上,可省去return关键字

    const fn3 = () => console.log('函数体只有一行代码时')

    const fn4 = (x,y) => x+y  

    console.log(fn4(1,2))  

  

    //箭头函数4:加括号的函数体返回对象字面量表达式

    //不使用箭头函数

    const fn6 = function(uname){

      return{uname:uname}

    }

    console.log(fn6('oo'));

    //使用箭头函数

    const fn5 = uname => ({uname:uname})

    console.log(fn5('gzbn'));

箭头函数this:箭头函数不会创建自己的this,它只会从自己的作用域链的上一层沿用this

2.3解构

2.3.1数组解构

是将数组的单元值快速批量赋值给一系列变量的简洁语法

    // 3.剩余参数 变量少, 单元值多

    const [tou,shou,...body] = ['头','手','脚','腿']

    console.log(tou); //头

    console.log(shou); // 手

    console.log(body);// (2) ['脚', '腿']

  

    // 4.  防止 undefined 传递

     const [x = 0, z = 0] = [1, 2]

    // const [a = 0, b = 0] = []

    console.log(x) // 1

    console.log(z) // 2

  

     // 5.  按需导入赋值

    const [u, v, , w] = [1, 2, 3, 4]

    console.log(u) // 1

    console.log(v) // 2

    console.log(w) // 4

  

    // 多维数组解构

    // const arr = [1, 2, [3, 4]]

    const [h, i, j] = [1, 2, [3, 4]]

    console.log(h) // 1

    console.log(i) // 2

    console.log(j) // [3,4]

2.3.2对象解构

是将对象属性和方法快速批量赋值给一系列变量的简洁语法

    // 1. 对象解构的变量名 可以重新改名  旧变量名: 新变量名

    const { uname: username, age } = { uname: 'gzbn', age: 18 }

    console.log(username);//gzbn

    console.log(age);//18

三.构造函数&常用函数

3.1深入对象

3.1.1创建函数的方式

  • {}
  • new Object({})
  • 构造函数
<body>

  <script>

    //创建对象 1

    const obj1 = {

      name:'leo',

      age:18

    }

  

    //创建对象2 new Object

    const obj2 = new Object({uname:'aa',age:18})

  

    //创建对象3 构造函数

    // 以下面为例:name age属于实例成员 count属于静态成员

    function Pig(name,age){

        this.name = name

        this.age = age

    }

    const obj3 = new Pig('ll',14)

    console.log(obj1);//{name: 'leo', age: 18}

    console.log(obj2);//{uname: 'aa', age: 18}

    console.log(obj3);//Pig {name: 'll', age: 14}

    Pig.count = 10

    console.log(Pig.count);// 10

  </script>

</body>

3.1.2实例成员与静态成员

实例对象的属性和方法即为实例成员;构造函数的属性和方法被称为静态成员

3.2内置构造函数

Object、Array、String、Number等

3.2.1Object

常用静态方法:

  • keys():获取所有的属性
  • values():获取所有的属性值
  • assign(NewObj,obj):对象拷贝

3.2.2Array

常用方法:

  • map():返回新数组,新数组里面的元素是处理之后的值,经常用于处理数据
  • forEach():不返回,用于不改变值,经常用于查找打印输出值
  • filter(): 筛选数组元素,并生成新数组
  • reduce():返回函数累计处理的结果,经常用于求和等
  • from():伪数组转换为真数组
  • splice() join() concat()…

3.2.3String

常用方法:

  • split():将字符串拆分成数组
  • substring():字符串截取
  • startWith():判断是否以某字符串开头
  • match():查找字符串

3.2.4Number

  • toFixed() 设置保留小数位的长度

四.构造函数深度解析

4.1编程思想

  • 面向过程编程:分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次 调用就可以了。
  • 面向对象编程:面向对象是把事务分解成为一个个对象,然后由对象之间分工与合作。
    总结
优点缺点
面向过程性能比面向对象高没有面向对象易维护、易复用、易扩展
面向对象易维护、易复用、易扩展性能比面向过程低

4.2构造函数

构造函数缺点:浪费内存

    function Star(uname,age){

      this.uname = uname

      this.age = age

      this.sing = function(){

        console.log('唱歌');

      }

    }

    const ldh = new Star('ldh',14)

    const zxy = new Star('zyx',14)

    console.log(ldh === zxy);//false

    console.log(ldh.sing === zxy.sing);//false

问题:ldh和zxy时两个不同的对象,所以创建了两个对象,创建了两个sing

4.3原型

4.3.1原型对象prototype

每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象

  • 通过原型分配的函数是所有对象共享的
  • 原型对象实例化不会多次创建原型上函数,节约内存
  • 构造函数和原型的this指向实例化对象
    作用:共享方法;把那些不变的方法,直接定义在 prototype 对象上

4.3.2constructor 属性

每个原型对象里面都有个constructor 属性(constructor 构造函数),属性指向该原型对象的构造函数

作用:指向该原型对象的构造函数

4.3.3对象原型__proto__

对象都会有一个属性__proto__ 指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有__proto__ 原型的存在。

对象原型里面也有一个 constructor属性,指向创建该实例对象的构造函数

4.3.4原型继承

问题:男人和女人都同时使用了同一个对象,根据引用类型的特点,他们指向同一个对象,修改一个就会都影响
需求:男人和女人不要使用同一个对象,但是不同对象里面包含相同的属性和方法
解决:构造函数 new 每次都会创建一个新的对象

4.3.5原型链

查找规则:

  • 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性
  • 如果没有就查找它的原型(也就是__proto__指向的 prototype 原型对象)
  • 如果还没有就查找原型对象的原型(Object的原型对象)
  • 依此类推一直找到 Object 为止(null)
  • 对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线
  • 可以使用 instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

五.进阶

5.1深浅拷贝

5.1.1浅拷贝

拷贝的是地址
常见方法:

  • 拷贝对象:Object.assgin() / 展开运算符 {…obj} 拷贝对象
  • .拷贝数组:Array.prototype.concat() 或者[…arr]

5.1.2深拷贝

拷贝的是对象,不是地址
常见方法:

  • lodash/cloneDeep
  • 通过JSON.stringify()实现

5.2异常处理

  • throw new Error() - 抛出异常
  • try/catch/finally - 捕获异常
  • debugger

5.3处理this

函数内不存在this,沿用上一级的,过程:向外层作用域中,一层 一层查找this,直到有this的定义

场景:

  • 不适用构造函数,原型函数,字面量对象中函数,dom事件函数
  • 适用需要使用上层this的地方

5.3.1改变this

  • fn.call(thisArg, arg1, arg2, …)
  • fn.apply(thisArg, [argsArray]) argsArray必须是个数组
  • fn.bind(thisArg, arg1, arg2, …) 不会调用函数
<body>

  <button>点击</button>

  <script>

    // call()

    const obj={age:14}

    function fn(x){

      console.log(this); //{age: 14}

      console.log(x);  //1

    }

     fn.call(obj,1)

    // apply()

    const arr = [100, 44, 77]

    const max = Math.max.apply(Math, arr)

    const min = Math.min.apply(null, arr)

    console.log(max, min)

    // bind()

    // 需求,有一个按钮,点击里面就禁用,2秒钟之后开启

    document.querySelector('button').addEventListener('click', function () {

      // 禁用按钮

      this.disabled = true

      window.setTimeout(function () {

        // 在这个普通函数里面,我们要this由原来的window 改为 btn

        this.disabled = false

      }.bind(this), 2000)   // 这里的this 和 btn 一样

    })    

  </script>

</body>

5.4性能优化

5.4.1防抖

触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间

5.4.2节流

指连续触发事件但是在 n 秒中只执行一次函数

案例

<!DOCTYPE html>

<html lang="en">

  

<head>

  <meta charset="UTF-8" />

  <meta http-equiv="X-UA-Compatible" content="IE=edge" />

  <meta name="viewport" content="width=device-width, initial-scale=1.0" />

  <title>Document</title>

  <style>

    .box {

      width: 500px;

      height: 500px;

      background-color: #ccc;

      color: #fff;

      text-align: center;

      font-size: 100px;

    }

  </style>

</head>

  

<body>

  <div class="box"></div>

  <script src="js/lodash.min.js"></script>

  <script>

    const box = document.querySelector('.box')

    let i = 1  // 让这个变量++

    // 鼠标移动函数

    function mouseMove() {

      box.innerHTML = i++

      // 如果里面存在大量操作 dom 的情况,可能会卡顿

    }

  

    // box.addEventListener('mousemove', mouseMove)

    // lodash 节流写法

    box.addEventListener('mousemove', _.throttle(mouseMove, 3000))

    // lodash 防抖的写法

    // box.addEventListener('mousemove', _.debounce(mouseMove, 500))

  

  </script>

</body>

  

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤枕_百年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值