JS高级笔记1(对象_原型_封装)

本文详细探讨了JavaScript中的对象创建、原型对象及其继承机制,包括原型链的概念和valueOf方法的解析。此外,还介绍了如何安全地扩展内置对象。接着,文章讲解了函数封装和this关键字的用法,特别是this在不同场景下的指向问题。最后,讨论了闭包的原理和作用,强调了闭包如何保存其创建时的词法环境,以及自调用函数在闭包中的应用。
摘要由CSDN通过智能技术生成

目录

 

1.对象

 2.原型对象学习

3. 原型链

4.函数封装

5. this学习

6.闭包 

1.对象

   创建对象的方式

    // 1. 对象字面量
    // 只能创建一次对象,复用性较差,代码冗余度高
    let obj = {
        name:'zxl',
        age:18
    };
    obj['sex'] = '男';
    obj.school = '南京高校';
    console.log(obj);

    //2. 使用内置构造函数
    let objB = new Object();
    objB.name='zxl';
    objB.age = 18;
    objB.sing = function () {
        alert("正在唱歌");
    };
    console.log(objB);

    //3. 封装简单的工厂函数(不推荐使用)
    function createPerson(name,age) {
        let objC = new Object();
        objC.name= name;
        objC.age =  age;
        objC.sing = function () {
            alert("正在唱歌");
        };
        return objC;
    }
    let objPerson = createPerson('小张',25);
    console.log(objPerson);

   //4.自定义构造函数 ***********
   //  用来初始化对象的函数,并且和new关键字同时出现
   //  构造函数名 首字母要大写
   function Person(name,age) {
       // 默认隐含的操作 把刚才用new新创建的对象赋值给this
       this.name = name;
       this.age = age;
       // 如果当前返回基本数据类型,那么其实应该还是返回的对象
       // 假如返回的是null和undefined 那么依旧返回的是当前的对象 
   }
   let p = new Person('小王',25);// new Object()
   console.log(p);

  /**
     * 谁调用this指代的是调用该方法的对象 ...
     * this谁调用就是谁...
     */

 

经典的继承

    let o = {
        name:'xx'
    };
    let objX = Object.create(o);
    console.log(objX.name);

    /**
     * 检测浏览器的兼容性
     */
    if (Object.create){
        let oC = Object.create(o);
    } else {
        Object.create = function () {
            function F() {

            }

            F.prototype = obj;
            return new F();
        };
        let oC = Object.create(obj);
    }

 2.原型对象学习

  JS中的继承大致等于 对象可以访问原型对象里面的方法 原型链

    /**
     * 访问原型
     * 构造函数.prototype
     * 原型默认的是一个空的对象
     * 原型作用:方法和属性可以共享
     *         解决构造方法中 全局变量污染的问题 以及代码结构的混乱

     */
    console.log(Person.prototype);

    /**
     * 给原型对象添加属性和方法
     */
    Person.prototype.exerciese = function () {
      console.log('我是通过在原型中添加的方法');
    };
    // ok调用成功了
    p.exerciese();
    console.log(Person.prototype);

    /**
     * 方法调用次序: 先在方法内部去查找 若未找到则在原型中查找 若无则报错

     *  在替换原型对象之前创建的对象的原型和在替换原型对象之后所创建的对象的原型不是同一个
     */

    /**
     * 访问原型 
     * 通过 对象.__proto__
     * 是一个非标准的属性
     */
    console.log(p.__proto__);

    /**
     * 通过原型去访问构造函数
       对象.构造方法  也是同样的效果进行访问
     * 

     * 对象.__proto__  以及 构造函数.__prototype__ 指向原型
     * 原型.constructor 指向构造函数     
     */
    console.log('--- 开始访问构造函数了--');
    console.log(Person.prototype.constructor);
    console.log(p.constructor);

 

 安全的扩展一个内置对象

    /**
     * 自己创建一个对象 然后让它(原型)去继承该对象 那么就可以很方便的进行拓展
     */
    function MyArray() {
        // 这样我们就可以进行拓展了
        this.name = '我是新复制的一个数组';
        this.hello = function () {
            alert('弹出了一个hello');
        }
    }
    //var arr = new Array();
    //MyArray.prototype = arr;
    MyArray.prototype = [];
    var myarr = new MyArray();
    myarr.push(1);
    myarr.push(2);
    console.log(myarr);

3. 原型链

/**
 * 原型链概念:
 * 每个构造函数都有原型对象
 * 每个对象都会有构造方法
 * 每个构造函数的原型都是一个对象
 * 那么这个原型对象也会有构造函数
 * 那么这个原型对象的构造函数也会有原型对象
 * 这样就会形成一个链式的结构 称为原型链
 */

函数的原型链

    let fool = new Function();
    console.log("fool的原型 = ");
    console.log(fool.prototype);
    // 函数的原型 结果为空函数

   let fool = new Function();
    console.log("空函数的原型 = ");
    console.log(fool.prototype.__proto__);

// 空函数的原型为空object的原型


 再下一层的原型为 null

重点**********

    /**
     * Object 和  Function 的原型链简单示意图
     * 
     * 对象构造函数  --> Function.Prototype --> Object.Prototype --> null
     * Function    --> Function.Prototype --> Object.Prototype --> null
     */

valueof 方法解析

    /**
     * valueOf 获取当前对象的值
     */

    console.log('-----valueOf开始-----');
    function Man() {
        this.name = '小李';
    }
    let man = new Man();
    console.log('man.toString() = '+man.toString());
    console.log('1+man = '+(1+man));

    // man.toString() = [object Object]
    // 1+man = 1[object Object]
    function Man() {
        this.name = '小李';
        this.valueOf = function () {
            return 128;
        }
    }
    
    // 在对象参与运算的时候:
    // 默认会先调用对象的valueOf方法,如果valueOf获取到的值无法进行运算就去调用
    // 对象的toString方法
    console.log("修改valueOf之后 1+man = "+(1+man));

instanceOf关键字学习 


    /**
     * instanceOf 判断构造函数的原型是否存在该对象的原型链上
     */
    console.log('测试instanceOf 关键字');
    console.log(p instanceof Object);

P --> P.ptototype --> Object.prototype-->null

 

4.函数封装

 function Song(name,singer){
        if (arguments.length !== 2){
            throw '参数有误';
        }
        this.songName = name;
        this.singer = singer;
    }

    /**
     * 歌曲管理系统
     * @constructor
     * 在当前对象的方法中 调用当前对象的其他方法或者内部的成员 需要使用this关键字
     *
     * JavaScript引擎在行末自动添加分号的机制
     */
    function SongManager() {
        this.songList = [ new Song('情书','张学友'),new Song('演员','薛之谦')];
        /**
         *  this.addSong = fun(x,y){
         *
         *  };
         */
    }

    /**
     * 最好是通过原型给其进行添加...
     * 资源初始化一次 单例
     * @type {{}}
     */
    SongManager.prototype = {
        // 增
        addSong:function addSong(name,singer) {
            this.songList.push(new Song(name, singer));
        },

        // 删
        delSongBySingerName:function delSongBySingerName(name){
            for (let i = 0;i< this.songList.length; i++){
                if (name === this.songList[i].singer){
                    // 使用splice进行删除
                    this.songList.splice(i,1);
                }
            }
        },

        querySongList:function () {
            for (let i= 0;i<this.songList.length;i++){
                let item = this.songList[i];
                console.log("歌曲名称 = "+item.songName+"  唱家 = "+item.singer);
            }
        }
    };

    let songManager = new SongManager();
    // 增测试
    console.log('增加...');
    songManager.addSong('今天你要嫁给我','陶喆');
    songManager.querySongList();
    // 删测试
    console.log('删除...');
    songManager.delSongBySingerName('薛之谦');
    songManager.querySongList();

5. this学习

重新申明一下: this指向了调用它的对象。

错误案例1: 这是最低级的错误 对象中引用其他对象需要使用this

    var sing = {
        name:'zxl',
        age:'小白',
        showName:function () {
            console.log('name = '+name+"  age = "+age);
        }
    };
    sing.showName();

    var sing = {
        name:'zxl',
        age:'小白',
        showName:function () {
            console.log('name = '+this.name+"  age = "+this.age);
        }
    };
    sing.showName();

    /**
     * 函数调用模式
     */
    window.age = 38;
    var obj = {
        age:18,
        getAge:function () {
            function foo() {
                console.log("函数里:"+this.age);
            }
            foo();
        }
    };
    // 38

进阶--- 二级嵌套 

    var sing = {
        name:'zxl',
        age:'小白',
        showName:function () {
            function getName(){
                console.log('name = '+this.name+"  age = "+this.age);
            }

            return getName();
        }
    };
    sing.showName();

    var sing = {
        name:'zxl',
        age:'小白',
        showName:function () {
            // *****重点*****
            let that = this;
            function getName(){
                console.log('name = '+that.name+"  age = "+that.age);
            }

            return getName();
        }
    };
    sing.showName();

6.闭包 

闭包和对象调用 

语法构成: 在一个函数中,返回内部函数 外部获得该引用。

闭包是由函数以及创建该函数的词法环境组合而成。这个环境包含了这个闭包创建时所能访问的所有局部变量

它们共享相同的函数定义,但是保存了不同的词法环境

    function f1() {
        let num = 123;
        // 函数体内 能够进行函数的调用
        function f2() {
            console.log(num);
        }
        f2();
        return {name: 'xx'};
    }
    console.log("----闭包测试开始了----");
    f1();

    let obj1 = f1();
    let obj2 = f1();
    console.log('---检查obj1和obj2 是否相等---');
    // 函数的每次调用 都会开辟新的空间  返回的对象都是新的 每次都不一样
    console.log(obj1 == obj2); // false
    /**
     * 函数内部调用
     *
     * 作用
     * 创建一个私有的作用域 保护数据
     * 外部想要访问数据 只能通过其内部函数提供的方法
     */
    function method1() {
        let num = 123;
        function innerMethod(a) {
            num = a;
            console.log(num);
        }
        return innerMethod;
    }

    let func = method1();
    console.log(func);
    func(789);

    // func 是执行method1函数时 创建的innerMethod函数的引用,
    // 而innerMethod仍然可以访问其词法作用域中的变量 num。

// 函数执行完毕了,内部函数依然可以访问其词法作用域中的变量。


    /**
     * 闭包 -- 获取多个参数方法 并设置值
     */
    function method2() {
        let name = '小李';
        let age = 18;
        return {
            getName:function () {
                return name;
            },
            getAge:function () {
                return age;
            }
        }
    }
    let method = method2();
    console.log(method.getName()); // 小李
    console.log(method.getAge());  // 18
       div.onclick = (function(j) {
            return function () {
                alert('我是第'+j+'个div');
            }
        })(i);



       function fool(j) {
           return function () {
               alert('我是第'+j+'个div');
           }
       }

       div.onclick = fool(i);

自调用函数

// 自调用函数
function f1() {
    (function (j) {
        console.log('自调用'+j)
    })(10);
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值