JS高级(ES6)

本文详细探讨了JavaScript中的面向对象编程,包括面向过程和面向对象的概念。重点讲解了ES6中的类和对象,如类的继承、构造函数和原型,以及原型链的工作原理。此外,还涵盖了ES6的新增特性,如let、const、解构赋值、箭头函数和模板字符串等,并讨论了正则表达式、继承方法和函数的高级用法,如bind、call和apply。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面向对象编程

面向过程编程(POP)

面向过程即分析好步骤,按照步骤编程。

面向对象编程(OOP)

找出对象,以对象功能来划分问题。
面向对象的特点:封装性 继承性 多态性
易维护、易复用、易扩展,性能比面向过程稍微低一点。

ES6中的类和对象

在这里插入图片描述

类class

是泛指的,抽象了对象的公共部分;
对象是特指某一个,通过实例化具体的对象。

  <script>
    //1.创建类class constructor为构造函数,new的时候会自动调用这个构造函数;
    class Star {
        constructor(uname, age) {
            this.name = uname;
            this.age = age;
        }
        //类里面的函数无需class 多个函数方法之间无需加逗号分隔
        sing(song) {
            console.log('我唱歌');
            console.log(this.name + song);
        }
    }
    //2.利用类创建对象new
    var ldh = new Star('刘德华', 20);
    console.log(ldh.name);
    console.log(ldh.age);
    ldh.sing('冰雨');
</script>

类的继承

包括extends spuer()

<script>

    class Father {
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }
        sum() {
            console.log(this.x + this.y);
        }
        say() {
            return '我是你爹';
        }
    }
    //extends 子类继承父类的属性和方法
    class Son extends Father {
        constructor(x, y) {
            //下面这种不对,因为father里的sum,this.x this.y指向的是father的构造函数
            // this.x = x;
            // this.y = y;
            super(x, y);//调用父类的(构造)函数
            //子类扩展自己新的方法,但super必须在子类this之前调用
            this.x = x;
            this.y = y;
        }
        say() {
            // console.log('我是你儿');
            console.log(super.say() + '的儿子');//子类通过super.函数名()调用父类的普通函数。
        }
        minus() {
            console.log(this.x - this.y);//指向的是子类的构造函数的this.x this.y
        }

    }

    var son = new Son(1, 2);
    son.sum();
    son.say();//就近原则,先在子类里查找有没有该方法
    var son2 = new Son(6, 1)
    son2.minus();
    son2.sum();

类的注意事项01

在这里插入图片描述

类的注意事项02(this指向问题)

<button>点击</button>
<script>
    var _that = null;
    var that = null;//全局变量,在任何一个地方都可以使用
    //类没有提升,要写在前面
    class Star {
        constructor(uname) {
            that = this;
            //constructor里面的this指向的是创建的实例对象,此处是ldh
            this.uname = uname;
            //this.song() 可以调用song函数
            this.btn = document.querySelector('button');
            this.btn.addEventListener('click', this.song);//都要加this 这里函数后面不要加小括号,不然马上就调用了,谁调用方法this就指向谁
        }
        song() {
            console.log(this);//this指向的是btn,所以下面是undefined
            console.log(this.uname);
            console.log(that.uname);//that指向的是constructor里面的this
        }
        dance() {
            _that = this;
            console.log(this);
        }
    }
    var ldh = new Star('刘德华');
    ldh.dance();//lhd调用了dance(),则dance里的this指向的是ldh

构造函数和原型

静态成员和实例成员

在这里插入图片描述

构造函数的问题

注意简单数据类型、复杂数据类型
构造函数存在内存浪费的问题,我们的方法function(){}是复杂数据类型,有多少个对象就会重复开辟多少个内存来存放方法。
在这里插入图片描述

构造函数原型 prototype

每个构造函数都有prototype属性,指向另一个对象叫做原型对象。
在这里插入图片描述
在这里插入图片描述

对象原型_proto_

为什么对象可以访问构造函数的原型对象的方法:对象身上系统自己添加一个_proto_指向我们的构造函数的原型对象prototype
在这里插入图片描述
在这里插入图片描述

constructor构造函数

原型对象prototype和对象原型_proto_都有constructor属性,他会指回原来的构造函数,有时候需要手动指回原来的构造函数:
当我们是赋值操作的时候,原型对象被直接修改,就需要手动添加constructor属性指回原来的构造函数。
在这里插入图片描述

构造函数、实例、对象原型之间的关系

在这里插入图片描述

原型链

只要是对象就有原型 _ proto_
原型一定指向一个原型对象 prototype
在这里插入图片描述

原型链成员查找规则

就近查找。
Object.prototype有toString()方法,其他的没有,但我们可以输出对象实例的toSrting()。

原型对象this指向

原型对象函数里面的this指向的仍然是实例对象。下面输出true
在这里插入图片描述

扩展内置对象

注意要使用“.”的形式来添加新的方法,不要赋值!
在这里插入图片描述

继承

ES6之前:构造函数+原型对象 组合继承

call()

作用:
1.调用函数;
2.改变this指向;注意第一个参数是改变this指向,后面的参数当函数的普通实参来看。
在这里插入图片描述

借用父构造函数继承属性

在这里插入图片描述
也可以添加子类自己的属性:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ES5中的新增方法

数组方法

forEach() 和filter()里面的return不会终止迭代
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

    var arr = [12, 66, 4, 88, 9, 7];
    var newArr = arr.filter(function (value, index) {
        return value % 2 == 0;
    });
    console.log(arr);
    console.log(newArr);

在这里插入图片描述
在这里插入图片描述

    //some 查找是否有满足条件的元素
    //some找到第一个符合条件的元素就停止循环了
    var flag = arr.some(function (value) {
        return value > 2;
    })
    console.log(flag);

在some里遇到return true就终止遍历。

字符串方法

去除字符串两边的空格:
str.trim();
可以用它来解决表单的bug:
在这里插入图片描述

对象方法

Object.keys(obj);
返回所有属性名组成的数组
在这里插入图片描述
在这里插入图片描述
Object.defineProperty()定义新的属性或修改属性。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
这样修改是失效的。
enumerable默认是false,无法遍历,Object.keys(obj)的时候就没有它。
在这里插入图片描述
当configurable为false则不允许被删除,且不允许再修改第三个参数的特性。
在这里插入图片描述

函数进阶

函数的定义和调用

在这里插入图片描述
所有的函数都是Function的实例(对象),即函数也是对象,函数也有原型。
在这里插入图片描述
// 函数的调用方式

    // 1. 普通函数
    function fn() {
        console.log('人生的巅峰');

    }
    // fn();   fn.call()
    // 2. 对象的方法
    var o = {
        sayHi: function() {
            console.log('人生的巅峰');

        }
    }
    o.sayHi();
    // 3. 构造函数
    function Star() {};
    new Star();
    // 4. 绑定事件函数
    // btn.onclick = function() {};   // 点击了按钮就可以调用这个函数
    // 5. 定时器函数
    // setInterval(function() {}, 1000);  这个函数是定时器自动1秒钟调用一次
    // 6. 立即执行函数
    (function() {
        console.log('人生的巅峰');
    })();
    // 立即执行函数是自动调用

this

 // 函数的不同调用方式决定了this 的指向不同
        // 1. 普通函数 this 指向window
        function fn() {
            console.log('普通函数的this' + this);
        }
        window.fn();
        // 2. 对象的方法 this指向的是对象 o
        var o = {
            sayHi: function() {
                console.log('对象方法的this:' + this);
            }
        }
        o.sayHi();
        // 3. 构造函数 this 指向 ldh 这个实例对象 原型对象里面的this 指向的也是 ldh这个实例对象
        function Star() {};
        Star.prototype.sing = function() {

        }
        var ldh = new Star();
        // 4. 绑定事件函数 this 指向的是函数的调用者 btn这个按钮对象
        var btn = document.querySelector('button');
        btn.onclick = function() {
            console.log('绑定时间函数的this:' + this);
        };
        // 5. 定时器函数 this 指向的也是window
        window.setTimeout(function() {
            console.log('定时器的this:' + this);

        }, 1000);
        // 6. 立即执行函数 this还是指向window
        (function() {
            console.log('立即执行函数的this' + this);
        })();

在这里插入图片描述

改变函数的this指向

bind() call() apply()

call():

在这里插入图片描述
在这里插入图片描述

apply()

在这里插入图片描述
打印的就是字符串,不是数组了在这里插入图片描述
注意数组里面加引号就是字符串,不然就是数字型
在这里插入图片描述

bind()

bind会绑定函数,但不会调用,也可以改变this指向。它相当于把函数进行了一个拷贝,返回一个新函数。
在这里插入图片描述
运用:(重要)

<body>
    <!-- 有一个按钮,点击之后禁用,3s后开启 -->
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <script>
        var btns = document.querySelectorAll('button')
        for (var i = 0; i < btns.length; i++) {
            btns[i].onclick = function () {
                this.disabled = true;
                setTimeout(function () {
                    this.disabled = false;
                }.bind(this), 3000)//这个this在函数外面,指向的是btn
            }
        }
    </script>
</body>
总结

在这里插入图片描述

严格模式

IE10以上才能执行

开启严格模式

为整个脚本开启严格模式:
在这里插入图片描述
或在写立即执行函数里
在这里插入图片描述
为某个函数开启严格模式:
在这里插入图片描述

严格模式的变化

变量:1.先声明再复制 2.不能delete
this:全局作用域下的this是undefined
下面这样就是把Star()当普通函数调用了,在普通模式下this指向window,相当于window.sex=‘男’,在严格模式下this指向undefined,this.sex执行会报错。
在这里插入图片描述

在这里插入图片描述
函数的变化:1.不能有重名的参数
函数必须是声明在顶层,且:
在这里插入图片描述

高阶函数

函数可以作为参数传递–如callback()
在这里插入图片描述
或将函数作为返回值输出–看闭包。

闭包(重要)

闭包的定义

闭包是有权访问另一个函数作用域中变量的函数。
被访问的变量所在的函数叫做闭包。
闭包的主要作用是延伸了变量的作用范围
局部变量通常是函数调用完毕就被销毁,但闭包使它不会立刻被销毁。

下面的例子:如何在全局作用域中访问局部作用域的变量。
在这里插入图片描述
在这里插入图片描述

<body>
    <ul class="nav">
        <li>111</li>
        <li>222</li>
        <li>333</li>
        <li>444</li>
    </ul>
    <script>
        //闭包应用-利用闭包输出当前li的索引号
        var lis = document.querySelectorAll('li');
        for (var i = 0; i < lis.length; i++) {
            // 利用for循环创建了4个立即执行函数
            (function (i) {
                lis[i].onclick = function () {
                    console.log(i);//此处有闭包产生(立即执行函数),i是立即执行函数里面的变量,在这里被调用了
                }
            })(i);//把实参i传给立即执行函数的形参i
        }
    </script>
</body>

(注意为什么不能之间打印i 因为回调函数(绑定了事件的 计时器)这种都属于异步任务,而for循环本来是个同步任务,已经执行到i++直到i=4了.

递归

如果一个函数在内部可以调用其本身,这个函数即递归函数。
死递归会导致栈溢出,必须要加退出条件return。

实例:求斐波那契数列

    //1、1、2、3、5、8...
    function fb(n) {
        if (n == 1 || n == 2) {
            return 1;
        }
        return fb(n - 1) + fb(n - 2)
    }
    console.log(fb(6));

浅拷贝和深拷贝

在这里插入图片描述

在这里插入图片描述

浅拷贝是把更深层次对象的地址拷贝,修改浅拷贝后的数据会把原数据也修改了。
下面这样obj的msg.age也会改变
在这里插入图片描述
另一种浅拷贝写法:
在这里插入图片描述
深拷贝拷贝深层次的对象会开辟新空间。

深拷贝方法:我们给新拷贝好的对象添加属性后原来的对象是不会改变的。

<script>
    //深拷贝
    var obj = {
        id: 1,
        name: 'hu',
        goods: {
            color: 'pink',
            price: 10000
        },
        arr: [1, 2, 3]
    }
    var o = {};
    function getCopy(newObj, oldObj) {
        for (var k in oldObj) {
            var item = oldObj[k];
            if (item instanceof Array) {//先判断数组,因为数组也属于对象,需要先筛出去
                newObj[k] = [];
                getCopy(newObj[k], item)
            } else if (item instanceof Object) {
                newObj[k] = {};
                getCopy(newObj[k], item)
            } else {
                newObj[k] = item;
            }
        }
    }
    getCopy(o, obj)

正则表达式

在这里插入图片描述

检测是否符合正则表达式要求规范

在这里插入图片描述

  // 1.利用RegExp创建
        // var regexp=new RegExp();
        // 2.利用字面量创建
        var rg = /123/;
        console.log(rg.test(123));//true
        console.log(rg.test('abc'));//false

/^abc$/
表示只能是abc
/^ [abc] $/ 表示三选一 a或者b或者c才可(aa 这种不可)
在这里插入图片描述
任意一个小写字母都是true:
/ ^ [a-z] $ /

下面的意思是小写大写字母数字下划线短横线多选一
在这里插入图片描述
如果中括号里面有^表示取反,就是不能包含的意思
在这里插入图片描述
量词:{x,y}大于等于3小于等于y
量词中间不要有空格
在这里插入图片描述
在这里插入图片描述

括号总结

下面只有最后一个true
在这里插入图片描述
让abc重复三次 在这里插入图片描述

预定义类(元字符)

在这里插入图片描述
在这里插入图片描述

正则表达式中的替换

在这里插入图片描述
全局匹配就可以匹配所有的符合的表达式,不然只能匹配第一个在这里插入图片描述在这里插入图片描述

ES6新增语法

let

let声明的变量只在所处的块级有效。
在这里插入图片描述
防止内层变量覆盖外层变量。
Var不具有这个属性:下面num为undefined abc=200
在这里插入图片描述
let可以防止循环变量变成全局变量,这样在for循环外面就不能访问到。
在这里插入图片描述
let关键字声明的变量没有变量提升
使用let关键字声明的变量有暂时性死区特性
let/const 命令会使区块形成封闭的作用域。若在声明之前使用变量,就会报错。
总之,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。
这在语法上,称为 “暂时性死区”
在这里插入图片描述

经典面试题
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

const关键字声明常量

1.具有块级作用域2.必须赋值在这里插入图片描述
3.常量值声明后不可更改:
直接赋值的操作就改了内存地址,是不行的。
在这里插入图片描述
但对于复杂数据类型可以这样改:
在这里插入图片描述
但不能在这里插入图片描述
解释:常量的含义是指向的对象不能修改,但可以修改对象的属性
在这里插入图片描述
直接修改obj={}的话相当于修改了obj存储的地址,但修改属性相当于obj存放的地址没有改变,只是改变里原地址里指向的属性的值。
参考:https://www.bilibili.com/video/BV15741177Eh?p=28

增强字面量写法

const name=‘hpy’
const age=16
const obj={
name,age
}
就直接以name为属性hpy为值了,age为属性16为值了。

同时function可以直接写,函数名(),如
run(){

}

解构赋值

在这里插入图片描述
在这里插入图片描述
注意下面真正的变量是myName,就是把’zhangsan’赋给myName…
在这里插入图片描述

箭头函数

箭头函数是用来简化函数定义语法的

    // 在箭头函数中如果函数体只有一句代码且执行结果就是函数返回值,此时可以省略{}和return
    const sum = (num1, num2) => num1 + num2
    console.log(sum(1, 2));

    // 如果形参只有一个,形参外侧的小括号也可以省略
    const v = a => {
        alert(a)
    }
    v(23)

箭头函数的this指向

箭头函数内部不绑定this,它里面的this和上下文的this指向一致

    function fn() {
        console.log(this);
        return () => {
            console.log(this);
        }
    }
    const obj = { name: 'zhangsan' }
    const v = fn.call(obj)
    v();

在这里插入图片描述
注意对象是不能产生作用域的,下面这样写this指向window 弹出100
在这里插入图片描述
注意:下面这样写的话this指向的是obj

    var obj = {
        age: 10,
        say: function () {
            alert(this.age)
        }
    }
    obj.say()

剩余参数

…args是一个数组,可以存放剩下的实参

    const sum = (...args) => {
        let total = 0;
        args.forEach(item => total += item);
        return total;
    }
    console.log(sum(10, 20, 30));
    console.log(sum(10, 20));

在这里插入图片描述

ES6的内置对象扩展

扩展运算符

在这里插入图片描述
逗号只是参数分隔符不会被输出

用于数组合并

在这里插入图片描述
在这里插入图片描述

将伪数组转为真正的数组

在这里插入图片描述

在这里插入图片描述
这样就可以调用数组的方法,如push…1

复制对象

展开运算符是不能用于对象的,但可以在构造字面量对象时使用:可以将已有对象的可枚举属性拷贝到新构造的对象中,用于浅拷贝和对象合并。

var obj1={foo:'bar',x:1};
var obj1={foo:'baz',y:2};
var obj={...obj1};
//克隆{foo:'bar',x:1}
var mergeobj={...obj1,...obj2};
//合并{foo:'bar',x:1,y:2};

Array的扩展方法

Array.from()

可以把伪数组(对象…)转为真正的数组
在这里插入图片描述
在这里插入图片描述

find()方法

find返回的是item
在这里插入图片描述

findIndex()

在这里插入图片描述

includes()

在这里插入图片描述

模板字符串

使用``声明的字符串叫做模板字符串

    let name = `zhangsan`
    console.log(name);
    //模板字符串拼接字符串:
    let name = `zhangsan`
    let sayHello = `我的名字叫${name}`

模板字符串可以换行,就是换行会显示出来;
调用函数:会显示函数的返回值
在这里插入图片描述

String的扩展方法

是否以某个字符串开头或结尾,返回布尔值。
在这里插入图片描述

在这里插入图片描述

Set数据结构

    const s1 = new Set(['a', 'b']);
    console.log(s1.size);//2
    const s2 = new Set(['a', 'b', 'a', 'b']);
    console.log(s2.size);//2
    const arr = [...s2]
    console.log(arr);//['a','b']

在这里插入图片描述
在这里插入图片描述

柯里化

    // 要执行add(1)(2)(3)=6或add(1)(2,3,4)(5)=15
    function add() {
      let args = [].slice.call(arguments)//把arguments类数组转为数组
      const inner = function () {
        args.push(...arguments)//把新的arguments push进刚刚的数组,这里还有闭包概念
        return inner//递归执行
      }
      inner.toString = function () {//inner有个隐式的toString的func会执行,返回return的东西,reduce会遍历数组前后两个数
        return args.reduce(function (a, b) {//
          return a + b
        })

      }
      return inner//在add里会调用inner
    }
    console.log(add(1)(2)(3));
    console.log(add(1, 2)(2, 3, 4)(5));

asnyc和defer的区别

1、defer 和 async 在网络读取(脚本下载)这块儿是一样的,都是异步的(相较于 HTML 解析)
2、两者的差别:在于脚本下载完之后何时执行,显然 defer 是最接近我们对于应用脚本加载和执行的要求的。defer是立即下载但延迟执行,加载后续文档元素的过程将和脚本的加载并行进行(异步),但是脚本的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。async是立即下载并执行,加载和渲染后续文档元素的过程将和js脚本的加载与执行并行进行(异步)。
3、关于 defer,我们还要记住的是它是按照加载顺序执行脚本的
4、标记为async的脚本并不保证按照指定它们的先后顺序执行。对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行。
5、async 对于应用脚本的用处不大,因为它完全不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值