JS高级的学习(二)

JS高级的学习(二)

set对象
  1. Set 是一个对象 存放数据 数据永远不会重复
  2. Set 当成是一个数组 遍历 使用 数组方法 find findIndex Map
    1. 数组转成 Set对象 const set = new Set([])
    2. Set对象转成 数组 const arr=[…set]
        //  旧的数组
        const list = [1, 2, 3, 4, 5]

        // 1.Set对象 需要被 new 出来使用
        // const set = new Set()
        const set = new Set(list)

        // 2.存放数据  调用 add方法
        set.add(7)
        set.add(8)
        set.add(8)
        set.add(9)

        console.log(set)
        // 3.把set对象 转成数组
        const arr = [...set]
        console.log(arr)
创建对象的n种方式
  1. 字面量 不方便维护,修改
  2. 工厂函数 封装 继承,参数一多也很麻烦
  3. 重点介绍 构造函数
        // 创建对象的方式:
		// 字面量	不方便维护 - 修改
        // const obj = { nickname: '悟空', height: 190 }
        // const obj1 = { nickname: '八戒', height: 100 }
        // const obj2 = { nickname: '沙和尚', height: 80 }

		// 工厂函数  封装 继承,参数一多也很麻烦
        function person(name, height, a, b, c, d, e) {
            return {
                nickname: name,
                height,
                a,
                b,
                c,
                d,
                e,
            }
        }
        const obj = person('悟空', 190)
        const obj1 = person('八戒', 100)
        const obj2 = person('沙和尚', 80)
        console.log(obj)
        console.log(obj1)
        console.log(obj2)

		// 最重要的是 构造函数
箭头函数 没有this指向
  1. 箭头函数没有内部的this
  2. 当函数执行体代码中 有出现了 this 慎用 箭头函数
        const obj = {
            username: "悟空",
            say: () => console.log(this) // this指向window
        }
        const funct1 = () => console.log(this) // this指向window
        obj.say()
        funct1()

        const button = document.querySelector("button")
        button.addEventListener("click", function () {
            this.innerText = "被修改了哈哈"
            console.log(this) // 按钮本身
        })
        button.addEventListener("click", () => {
            // this.innerText = "被修改哈" // error,this指向window了
            console.log(this) // window
        })
全局函数的this的指向
  1. 一般来说 this的指向 判断依据 谁调用了 函数 this 指向谁
  2. 其实 当定义了全局的函数的时候,默认是挂载到了window 全局变量上
  3. 全局函数 其实就是 window的一个属性而已 只不过 平时写代码的时候 可以省略这个window
    1. 当定义全局的函数的时候 本质是给window添加了一个 属性(函数类型)
    2. 当调用这个函数的时候 如:person() 本质 window.person() window 可以被省略而已
        function person() {
            console.log("ABC")
            console.log(this) // this指向window
        }
        person() // 调用了this,this指向了window

        window.sonPerson = function () {
            console.log('ABC')
            console.log(this) // this指向window
        }
        window.sonPerson() // 调用了this,this指向了window

        const obj = {
            username: "悟空",
            say() {
                console.log(this) // this指向obj
            }
        }
        obj.say()
构造函数
  1. 构造函数 本质 其实也是一个函数

  2. 作用 用来创建对象

  3. 以前见过构造函数

  4. 只要它被new 它就是构造函数

    1. 如:Person 构造函数 首字母是大写(规范)
    2. 如:per 被new出来的对象是 实例
        // Person 就是一个构造函数 被new
		function Person() {}

        // per 就是实例
        const per = new Person()
构造函数的this
  1. 每一个构造函数中 都存在 一个 魔鬼 this
  2. 构造函数 默认情况下 就是返回了 this
  3. this 等于你所new出来的实例
        // 只要给构造函数中的this 添加 属性或者方法
        // 那么 实例 自然拥有对应的属性和方法

        function Person() {
            this.username = '悟空' // Person增加了一个属性
            this.add = function () {} // Person增加了一个方法
            this.clear = function () {}
        }

		// 注意:
        console.log(Person.username) // 无法拿到Person的元素
        console.log(Person.username = '沙和尚') // 控制台显示 沙和尚,但实际Person里面的username还是 悟空
        console.log(Person) // username属性还是 悟空
        console.log(this.username) // 无法拿到Person的元素

        const per = new Person()
        per.nickname = '八戒' // 直接添加,per有、per2没有
        const per2 = new Person()

        console.log(per)
        console.log(per2)
        console.log(per2.username) // 可以拿到Person的元素
构造函数的弊端
        function Person() {
            this.say = function () {}
        }

        // p1 和 p2 没有共享一个方法(占更多的内存)
        const p1 = new Person()
        const p2 = new Person()
        console.log(p1 === p2) // false 两个对象的比较 内存地址 
        console.log(p1.say === p2.say) // false 两个函数 存放在不同地址中

        // s1 和 s2 共享一个方法
        const s1 = new Set()
        const s2 = new Set()
        console.log(s1 === s2) // false 两个对象的比较 内存地址 
        console.log(s1.say === s2.say) // true 两个函数 存放在相同地址中
构造函数-方法指向同一个(这个全局(方法)变量不推荐,后面的 构造函数+原型 更好 )
  1. 值类型 是存在 栈空间 适合存放 固定大小的数据
  2. 引用类型(对象、数组、函数) 存在 堆空间 适合存放大小不固定的数据
  3. new了两个对象的时候, 两个对象的内存地址 不相等
  4. 希望 两个对象的方法 内存地址是相等
    1. 在构造函数中 当我们定义方法的时候 一般都不会只在 构造函数中写死
    2. 让 方法 都指向外部 单独声明的方法 多个实例去共享方法
  5. 缺点:污染全局变量,意思是有其他人可能使用这些属性、方法,就会造成覆盖
        // newSay 全局(方法)变量
		function newSay() {
            console.log('外部单独的newSay方法')
        }

        function Person() {
            this.say = newSay
        }

        const p1 = new Person()
        const p2 = new Person()
        console.log(p1 === p2) // false 
        console.log(p1.say === p2.say) // true
构造函数基本使用(这个全局(方法)变量不推荐,后面的 构造函数+原型 更好 )
  1. 构造函数的属性
    1. 函数类型的属性(指方法):一般都是写在外部
    2. 非函数类型的属性(指属性):一般是写在内部
        // say 全局(方法)变量
		function say() {
            console.log('这个是Person的一个方法', this.name)
        }
        // fly 全局(方法)变量
        function fly() {
            console.log(this.name, '要起飞')
        }

        function Person(name, height) {
            this.name = name
            this.height = height
            this.say = say
            this.fly = fly
        }
        const p1 = new Person('八戒', 150)
        p1.say()
        p1.fly()
        console.log(p1)
        console.log(p1.name, p1.height)
构造函数+原型(es6比es5(构造函数+原型)更好)
  1. 原型 本质 是一个对象
  2. 当创建一个构造函数的时候 原型 就被创建了
  3. 如果我们在原型对象上 增加一个属性或者方法 那么 实例 拥有所增加的属性或者方法
  4. 原型 就是 DNA;构造函数 就是 父亲;实例 就是 孩子
        function Person() {
            this.name = '悟空'
            this.b = function () {}
        }
        console.log(Person.prototype)

        // 访问原型
        Person.prototype.a = function () {
            console.log('这个是a方法')
        }

        const p1 = new Person()

        console.log(p1)
        p1.a()
原型实现方法的继承-prototype
        function Person() {}

        Person.prototype.say = function () {
            console.log('father', '父亲定义的say方法')
        }
        const father = new Person()

        function SonPerson() {}

        //  让孩子SonPerson去复用父亲Person的方法  即继承父亲的方法
        SonPerson.prototype.say = Person.prototype.say
        // 添加其他方法
        SonPerson.prototype.jump = function () {
            console.log('son', '孩子自己的方法')
        }
        const son = new SonPerson()

        Person.prototype.say() // ok:Person的原型(prototype)的方法say()
        SonPerson.prototype.say() // ok:SonPerson的原型(prototype)的方法say()

        // son.say = father.say // 等同于 SonPerson.prototype.say = Person.prototype.say  前提条件:Person和SonPerson都被 new 后
        son.say()
        son.jump()
原型实现属性的继承-call
        function Person(name, color, height, weight) {
            this.name = name
            this.color = color
            this.height = height
            this.weight = weight
        }

        function SonPerson(name, color, height, weight, nickname, gender) {
            // Person父亲中也有  注意:this不能忘写
            Person.call(this, name, color, height, weight) // 属性的继承 

            // SonPerson孩子
            this.nickname = nickname
            this.gender = gender
        }

        const son = new SonPerson('悟空', '黄色', 150, 250, '弼马温', '公')
        console.log(son)
		console.log(son.name)
原型快速继承
   		// 作用:快速将父亲的原型复制到儿子上
        function Person() {}
        Person.prototype.add = function () {}
        Person.prototype.remove = function () {}
        Person.prototype.clear = function () {}

        function SonPerson() {}
        // SonPerson.prototype.add= Person.prototype.add
        // SonPerson.prototype.remove= Person.prototype.remove
        // SonPerson.prototype.clear= Person.prototype.clear

        // 让儿子的原型 指向 父亲的原型
        // SonPerson.prototype = Person.prototype // error:堆地址联系在一起,修改一个,另一个也被修改

        // 对象复制(剩余运算符)
        SonPerson.prototype = {
            ...Person.prototype
        }

        SonPerson.prototype.cunstructor = SonPerson // 添加方法到SonPerson的原型
        SonPerson.prototype.del = function () {} // 添加方法到SonPerson的原型

        const son = new SonPerson()
        console.log(son)

        const per = new Person()
        console.log(per)
es6类的基本使用
  1. 构造函数 来创建对象
  2. 对象 两种属性信息
    1. 非函数类型的属性(指属性)
    2. 函数类型的属性(指方法)
        // es6 新 简洁  class 面向对象
        class Person {
            // this不用写,一写就报错
            name = '悟空'
            color = '红色'
            say() {
                console.log(this.name, this.color)
            }
            fly() {
                console.log(this.name, '起飞')
            }
        }

        // es5 原型链方式实现  面向对象
        function Person2() {
            this.name = "悟空"
            this.color = "紫色"
        }
        Person2.prototype.say = function () {
            console.log(this.name, this.color)
        }
        Person2.prototype.fly = function () {
            console.log(this.name, '降落')
        }

        const p1 = new Person()
        p1.say() // 悟空 红色
        p1.fly() // 悟空 起飞
        
        const p2 = new Person2()
        p2.say() // 悟空 紫色
        p2.fly() // 悟空 降落
es6类的(动态)基本使用
        //   使用 class 来定义属性的时候
        //     1.如果 这个属性 写死了
        //       class Person {
        //         name="悟空"
        //         color="黄色"
        //       }
        //     2.如果 属性 可以由外部传入 必须使用构造器
        //       constructor(name,color){
        //         this.name=name
        //         this.color=color
        //       }

        class Person {
            // 构造器
            constructor(name, color) {
                // 当 Person被new的时候 这个构造器 就会被调用
                console.log('Person被new了')
                console.log(name, color)
                
                // this 还是指向 实例  注意:this要写
                this.name = name
                this.color = color
            }
            say() {
                console.log(this.name, this.color)
            }
        }

        const p1 = new Person('悟空', '红色')
        p1.say()
        console.log(p1)
es6类实现属性和方法的继承
        // // es5类 去实现继承
        // function Person() {
        //     this.name = "父亲"
        // }
        // Person.prototype.say = function () {
        //     console.log(this.name, "父亲的say方法")
        // }

        // function SonPerson(name) {
        //     Person.call(this, name) // 属性的继承
        // }
        // SonPerson.prototype.say = Person.prototype.say // 方法的继承

        // const son = new SonPerson
        // console.log(son.name)
        // son.say()

        // es6类 去实现继承
        class Person {
            name = '父亲'
            say() {
                console.log(this.name, '父亲的say方法')
            }
        }

        // 直接实现了 继承父亲的属性和方法
        class SonPerson extends Person {}
        // 孩子实例 拥有 父亲 name属性和say方法
        const son = new SonPerson()
        console.log(son)
        console.log(son.name)
        son.say()
es6类实现(动态)属性和方法的继承
        //   对于孩子来说 
        //   1.如果写了  extends 而且 还写 constructor 
        //     那么在 constructor 必须要调用super 固定语法
        //   2.之前只写  extends 不用写super 因为没有写 constructor
        class Person {
            constructor(name, color) {
                this.name = name
                this.color = color
            }
            say() {
                console.log(this.name, this.color)
            }
        }

        class SonPerson extends Person {
            // 默认的代码
            constructor(name, color, height, weight) {
                super(name, color) // 调用父亲的构造器 给孩子 添加属性
                this.height = height
                this.weight = weight
            }
        }

        const son = new SonPerson('悟空', '紫色', 100, 200)
        console.log(son)
        console.log(son.height)
        son.say()
检测数据类型(检测实例被这个构造函数 new)
        //  检测 基本的数据类型 typeof
        //  检测 引用数据类类型 intanceof
        //  检测 这个实例是不是被某个构造函数 new 出来 

        console.log(typeof '') // string
        console.log(typeof 1) // number

        function Person() {}
        class SuperPerson {}
        const p1 = new Person()
        const s1 = new SuperPerson()

        console.log(p1 instanceof Person) //  true
        console.log(s1 instanceof SuperPerson) // true
        console.log(p1 instanceof SuperPerson) // false
对象中的this和call
  1. this 范围很广 主要在 对象中来学习
  2. this 指向 对象本身 可以通过 call 方法来修改
  3. call 在调用方法的时候,可以修改 this 的指向
  4. call 在调用方法的时候,可以传递参数
        const obj = {
            height: 100,
            username: '悟空',
            say(a) {
                console.log(this, a) // this指向 obj
            },
        }
        const newObj = {
            username: '八戒'
        }
        obj.say()
        console.log(obj)
        obj.say.call() // call修改this的指向,变成window

        console.log('----------------------------------')
        obj.say(123)
        obj.say.call(this, 123) // this指向 window
        obj.say.call(newObj, 123) // this指向 newObj
对象添加属性的方式
        // 对象添加属性的普通方式
        const newObj = {
            a: 1,
            b: 1,
        }
        newObj.c = 2
        console.log(newObj)

        // 在对象中  this = 对象本身    this =  我自己
        // 当成普通的对象
        const obj = {
            a: 1,
            e: 1,
            add() {
                // 给对象添加属性  封装到一个普通的函数中
                obj.a = 3 // 会覆盖原来的a属性
                obj.b = 3
                // 等同上面  obj修改成this
                this.c = 4
                this.d = 4
            }
        }
        console.log(obj) // add方法没使用时,只有a、e、add()
        obj.add() // 让方法帮我们添加属性
        console.log(obj)
动态给对象添加属性-call
        // 当成普通的函数
        function person(name, color, height, weight) {
            this.name = name
            this.color = color
            this.height = height
            this.weight = weight
        }
        // 定义一个空的对象
        const obj = {}

        person.call(obj, '悟空', '红色', 150, 250) // obj 借用了person方法 来给自己的属性赋值
        // 1.调用了 Person 方法
        // 2.方法内部 给 this赋值   this 等于 obj
        // 3 this.name=悟空 =>  obj.name = 悟空  //  赋值动作 
        // 3 this.color=黄色 =>  obj.color = 黄色  //  赋值动作 
        // 3 this.height=150 =>  obj.height = 150  //  赋值动作 
        // 3 this.weight=250 =>  obj.weight = 250  //  赋值动作

        console.log(obj) // 拥有了 Person 函数中一些属性 
修改this指向:bind、call、apply
  1. call 和 apply 会在调用原函数的同时也修改this的指向
  2. bind会修改this指向 但是 不会直接调用原函数 而是会返回一个 修改了this指向 的新函数
  3. call 和 apply 区别 传递参数的方式不同而已
    1. 如:obj.say.call(newObj,1,2) // 数字,字符串
    2. 如:obj.say.apply(newObj,[1,2]) // 数组
  4. 默认情况下 this的指向 谁调用了this,this 指向谁
       const obj = {
            username: '悟空',
            say() {
                console.log(this.username, 'obj中的say方法 ')
            },
            say1(a, b) {
                console.log(a, b)
            },
        }

        const newObj = {
            username: '八戒',
        }

        obj.say.call(newObj)
        obj.say.apply(newObj)

        const fn = obj.say.bind(newObj) //  返回一个新的函数  新函数内部 修改this指向的功能
        fn()

        console.log('---------------------------')
        obj.say1.call(newObj, 1, 2)
        obj.say1.apply(newObj, [1, 2]) // 参数必须要以数组的形式来传递

        const fn1 = obj.say.bind(newObj)
        fn1(1, 2)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值