JS高级02


小概

本章学习内容:原型链的介绍理解(图解),instanceOf,arguments复习。代码量虽少,但是都是一些理解性的知识。关键字:prototype ,__ proto __ ,constructor ,Object , Function , instanceOf.


1. 原型链

对象都有原型,原型也是对象,那原型也有原型,这样就形成了一个链式结构 ,称为原型链
.
原型链的作用:体现在对象访问成员的访问规则,一个对象去点一个方法,先在对象自己上找,如果没有就去自己的原型找,原型没有就沿着原型链一直往上查找,如果找不到就报错或是返回undefined
原理其实是继承

        function Student(name, age) {
            this.name = name;
            this.age = age;
            this.swmming = function () {
                console.log('我在游泳....');
            }
        }
        //每一个学生都有一个学习的方法
        Student.prototype.study = function () {
            console.log('我是学生,我在学习....');
        }
        //每一个学生都一个type属性,都是人. 
        Student.prototype.type = '人';

        //实例化一个学生对象. 
        let s1 = new Student('闫正', 34);
        console.log(s1);

        // console.log(s1.name);//'闫正'
        // console.log(s1.type);//'人'
        // console.log(s1.sb);//undefined

        // s1.swmming();//对象自己有,可以调用
        // s1.study();//对象虽然自己没有,但是原型有,所以也可以调用. 
        // s1.dsb();//对象自己没有,原型也没有,所以报错了


        s1.toString(); //上层原型对象里有tostring这个方法

1.2 js内置对象的原型

        //内置对象的原型链. 
        //1.数组
        // let arr = [10,20,30]; //let arr = new Array(10,20,30);
        // console.log(arr);
        // console.log(arr.__proto__ === Array.prototype); //true

        // console.log(arr.__proto__.__proto__.constructor);//Object()
        // console.log(arr.__proto__.__proto__ === Object.prototype);//true

        //------------------------------------
        //为什么数组对象toString()得到的结果和普通对象toString()得到的结果不一样? 
        //arr1调用的toString()是Array.prototype中的toString();
        //obj1调用的toString()是Object.prototype中的toString();
        // let arr1 = new Array(10,20,30);
        // console.log(arr1.toString()); //'10,20,30'

        // let obj1 = new Object();
        // console.log(obj1.toString());//'[object Object]'

        //2.日期对象
        // let date1 = new Date();
        // //用console.log()直接打印日期对象,相当于是日期对象调用了toString()方法. 
        // console.log(date1);
        // console.log(date1.toString());
        // console.log(date1.toLocaleString());
        // //如果想要查看日期对象本身,就要使用console.dir();
        // console.dir(date1);
        // console.log(date1.__proto__ === Date.prototype);//true

        // console.log(date1.__proto__.__proto__.constructor); //Object()
        // console.log(date1.__proto__.__proto__ === Object.prototype);//true

        //3.dom对象
        // let div1 = document.querySelector('div');
        // let p1 = document.querySelector('p');
        // let a1 = document.querySelector('a');


        // console.log(div1.__proto__ === HTMLDivElement.prototype);//true

        //移除属性
        //removeAttribute()这个方法在Element.prototype原型中定义的. 
        //div1.removeAttribute('aaa');

        //普通对象
        let obj = {
            name:'德磊',
            age:18
        };
        console.log(obj);
        //报错了,obj.removeAttribute is not a function
        //普通对象的原型中是没有这个方法的. 
        //这个方法是地能以在Element.prototype原型中的. 意味着只有元素才能点出这个方法来. 
        obj.removeAttribute('age');

原型中的方法是可以重写的,Object.toString() ,Array.toString()重写了。

1.2 函数

函数是一个对象,是由Function构造函数实例化出来的.

        //1.函数也是一个对象. 
        function test(){
            console.log('我是一个函数');
        }
        //把函数当做一个对象,往中添加sb属性和dsb方法.
        test.sb = '随便';
        test.dsb = function(){
            console.log('你是一个da随便...');
        }
        //验证. 
        console.dir(test);
        console.log(test.sb);
        test.dsb();

        //2.既然函数是一个对象,那这个对象是由哪个构造函数实例化的呢?
        console.log(test.__proto__.constructor);//Function()
        console.log(test.__proto__ === Function.prototype);//true


        console.log(test.__proto__.__proto__.constructor);//Object()
        console.log(test.__proto__.__proto__ === Object.prototype);//true
      
        //1. 声明了一个无参无函数体的函数. 
        // let fn1 = new Function();
        // console.log(fn1);

        //2. 声明一个无参有函数体的函数. 
        // let fn2 = new Function('console.log("德华你好....")');
        // console.log(fn2);
        // fn2();

        //3. 声明一个有参有函数体的函数. 
        // let fn3 = new Function('num1','num2','console.log(num1+num2,"哈哈哈");');
        // fn3(10,20);

        //4. 声明一个有参有函数体有返回值的函数. 
        // let fn4 = new Function('num1','num2','console.log(num1+num2,"哈哈哈");return num1*10;');
        // console.log(fn4(10,20));;

函数可以像对象一样,通过函数名 . 属性值 =属性值,或者函数名 . 方法名=function() 给函数自身添加属性和方法 并且 通过点语法来调用

2. 静态成员和实例成员

静态成员: 构造函数直接点出来的.
实例成员: 实例化对象点出来的.

        function Student(name,age){
            this.name = name;
            this.age = age;
            this.sayHi = function(){
                console.log('呵呵呵呵');
            }
        }

        //把Student看成是一个对象,往中添加一个sayHi方法
        Student.sayHi = function(){
            console.log('你好');
        }

        Student.sayHi(); //静态成员. 

        //实例化对象. 
        let s1 = new Student('正正',19);
        console.log(s1.name); //实例成员
        s1.sayHi(); //实例成员

3. instanceOf

语法: 对象 instanceof 构造函数
作用: 判断这个构造函数的prototype属性 在不在这个对象的原型链上,如果在返回true,如果不在返回false.
实际用途:

  1. 可以用来判断这个对象的构造函数(判断类型)
  2. 可以放心的去使用这个构造函数的prototype里面的成员
        //1. 
        // let arr = [10,20,30];
        console.log(arr instanceof Array);//true
        console.log(arr instanceof Object);//true


        //2. 
        //根据instanceof运算符的语法来看,前面的Object应该看成是对象,后面的Object看成是构造函数. 
        Object对象的原型链:  Function.prototype => Object.prototype => null
        console.log( Object instanceof Object); //true
        console.log( Object instanceof Function);//true


        //3. 
        //根据instanceof运算符的语法,前面的Function看成是对象, 后面的Function看成是构造函数. 
        //Function对象的原型链: Function.prototype => Object.prototype => null
         console.log(Function instanceof Function);//true
         console.log(Function instanceof Object);//true

4. Object.prototype成员介绍

        //1.constructor
        //指向构造函数

        //2.hasOwnProperty
        //语法: 对象.hasOwnPropert('属性名/方法');
        //作用: 判断这个属性/方法 是否是属于对象自己的,如果是就返回true,否则返回false, 
        // let obj = {
        //     name:'正正',
        //     age:18,
        //     sayHi:function(){
        //         console.log('你好');
        //     }
        // }
        // obj.__proto__.type = '人';
        // obj.__proto__.sayHello = function(){
        //     console.log('sayhello');
        // }
        // console.log(obj.hasOwnProperty('name'));//true
        // console.log(obj.hasOwnProperty('sayHi'));//true
        // console.log(obj.hasOwnProperty('type'));//false
        // console.log(obj.hasOwnProperty('sayHello'));//false


        //3.isPrototypeOf
        //语法: 对象1.isPrototypeOf(对象2);
        //作用: 判断对象1是否是对象2的原型, 如果是返回true,否则返回false. 
        // let obj1 = {name:'哈哈1'};
        // let obj2 = {name:'呵呵2'};
        // obj2.__proto__ = obj1;//这句话的意思是修改obj2的原型为obj1,也就是说现在obj1是obj2的原型了.
        // console.log(obj1.isPrototypeOf(obj2));//true

        // let arr = [10,20,30];
        // console.log(Array.prototype.isPrototypeOf(arr));//true


        //4. propertyIsEnumerable
        //语法: 对象.propertyIsEnumerable('属性名/方法名');
        //作用: 判断属性是否是对象自己的,以及是否可以遍历. 都符合才是true. 
        // let obj = {
        //     name:'正正',
        //     age:18,
        //     sayHi:function(){
        //         console.log('你好');
        //     }
        // }
        // obj.__proto__.type = '人';
        // obj.__proto__.sayHello = function(){
        //     console.log('sayhello');
        // }
        // //自己的属性以及原型中自己添加的属性,都是可以遍历的. 
        // // for(let key in obj){
        // //     console.log(key);
        // // }

        // console.log(obj.propertyIsEnumerable('name'));//true
        // console.log(obj.propertyIsEnumerable('age'));//true
        // console.log(obj.propertyIsEnumerable('sayHi'));//true
        // console.log(obj.propertyIsEnumerable('type'));//false
        // console.log(obj.propertyIsEnumerable('sayHello'));//false

        //5. toLocaleString
        // 本地字符串. 


        //6. toString
        // 字符串 
        // [object type], 其中type是数据类型


        //7. valueOf
        // 原始值
        // let num = new Number(10);
        // num.toString();
        // console.log(num);
        // console.log(num.toString());//'10'
        // console.log(num.valueOf());//10

5. 函数作为对象的成员介绍.

5.1 caller

如果test2函数是在test1函数中调用的,那么test2函数的caller就是test1.
test1没有在任何一个函数中调用,那test1的caller就是null.

        function test1(){
            console.log('我是test1函数');
            console.log(test1.caller);
            test2();
        }
        function test2(){
            console.log('我是test2函数');
            console.log(test2.caller);
        }
        test1();

5.2 length

形参长度(个数)

        function test1(){
            console.log('我是test1函数');
            console.log(test1.caller);
            test2();
        }
        function test2(){
            console.log('我是test2函数');
            console.log(test2.caller);
        }
        test1();

5.3 name

函数名

5.4 prototype原型

每个构造函数都有一个原型 :函数名.prototype,构造函数的实例对象中也有一个参数__proto__ 指向 构造函数的原型。

5.5 arguments

是一个伪数组 用于存放实参的值

        //也是一个伪数组,也是存放实参的值. 
        //和以前我们学的arguments不是同一个东西. 
        //以前我们学的arguments和形参一一对应, 今天的这个并没有一一对应. 
        function test1(num1,num2){
            num1 = 1000;
            console.log(arguments); //和形参一一对应的
            console.log(test1.arguments);//并没有和形参一一对应. 
            console.log(arguments === test1.arguments);//false
            console.log(test1.arguments.__proto__ === Array.prototype);//false
        }
        test1(100,200,300);

这个了解即可,arguments用的更多,test1.arguments不知道应用场景是什么。

总结

是不是感觉很绕?俺也一样,反正记住构造函数有一个原型对象,构造函数操作原型对象:构造函数.prototype ,原型对象里面的constructor指向构造函数;构造函数实例化的p1,实例对象.__proto __指向原型。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值