美文网首页
原型、原型链

原型、原型链

作者: 原上的小木屋 | 来源:发表于2019-04-10 23:11 被阅读0次

    如下代码中, new 一个函数本质上做了什么?

    function Modal(msg){
        this.msg = msg
    }
    var modal = new Modal()
    
    1. 创建一个新的对象,这个对象的类型是object;
    2. 查找Modal的prototype上的所有方法、属性,复制一份给创建的Object
    3. 将构造函数Modal内部的this指向创建的Object
    4. 创建的Object的proto指向Modal的prototype
    5. 执行构造函数Modal
    6. 返回新创建的对象给变量modal

    画出如下代码的原型图。

    function People (name){
      this.name = name;
    }
    
    People.prototype.walk = function(){
      console.log(this.name + ' is walking');  
    }
    
    var p1 = new People('飞天虎');
    var p2 = new People('tiger');
    
    1.png

    扩展 String 的功能增加 reverse 方法,实现字符串倒序

    var str = 'hello jirengu'
    var str2 = str.reverse()
    console.log(str2) //  'ugnerij olleh'
    
    String.prototype.reverse=function(){
        var str=this
        var newstr=''
        for(var i=str.length-1;i>=0;i--){newstr+=str[i]}
        return newstr
    }
    

    有如下代码,代码中并未添加 toString方法,这个方法是哪里来的?画出原型链图进行解释

    function People(){
    }
    var p = new People()
    p.toString()
    
    image.png
    image.png
    • 记当前对象为p,查找p属性、方法
    • 没有找到,通过p的proto属性,找到其类型People的prototype属性(记为prop)继续查找
    • 没有找到,把prop记为obj做递归重复步骤一,通过类似方法找到prop的类型Object的 prototype进行查找,直至找到toString方法

    有如下代码,解释Person、 prototype、proto、p、constructor之间的关联。

    function Person(name){
        this.name = name;
    }
    Person.prototype.sayName = function(){
        console.log('My name is :' + this.name);
    }
    var p = new Person("xiaoweimei")
    p.sayName();
    
    • 我们通过函数定义了类Person,类(函数)Person自动获得属性prototype
    • Person是一个构造函数,构造函数构造出实例 p,
    • p是构造函数Person的一个实例,p的 proto 指向了Person的prototype属性,
    • prototype是构造函数内部的原型对象,所以拥有contructor和proto属性,其中contructor属性指向构造函数Person,proto指向该对象的原型.

    上一题中,对对象 p我们可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链

    • 每个构造函数(constructor)都有一个原型对象(prototype),原型对象都包含一个指向构造函数的指针,而实例(instance)都包含一个指向原型对象的内部指针.如果试图引用对象(实例instance)的某个属性,会首先在对象内部寻找该属性,直至找不到,然后才在该对象的原型(instance.prototype)里去找这个属性.
    1. 首先会在instance1内部属性中找一遍;
    2. 接着会在instance1.proto(constructor1.prototype)中找一遍,而constructor1.prototype 实际上是instance2, 也就是说在instance2中寻找该属性p1;
    3. 如果instance2中还是没有,此时程序不会灰心,它会继续在instance2.proto(constructor2.prototype)中寻找...直至Object的原型对象
      这种搜索的轨迹,形似一条长链, 又因prototype在这个游戏规则中充当链接的作用,于是我们把这种实例与原型的链条称作原型链

    对String做扩展,实现如下方式获取字符串中频率最高的字符

    var str = 'ahbbccdeddddfg';
    var ch = str.getMostOften();
    console.log(ch); //d , 因为d 出现了5次
    
        String.prototype.getMostOften = function(){
            var Str = {};
            var num;
            for(var i=0;i<this.length;i++){
                num = this[i];
                if(!Str[num]) {
                    Str[num] = 1;
                }else{
                    Str[num]++;
                }
            }
            var maxNum = 0;
            var strKey;
            for(var key in Str){
                if(Str[key] > maxNum){
                    maxNum = Str[key];
                    strKey = key;
                }
            }
            return strKey;
        };
    

    instanceOf有什么作用?内部逻辑是如何实现的?

    作用:instanceOf 用于判断当前引用类型对象是不是某个构造函数的实例

    var a=[1,2,3,4],
        b={"acorn":1,"z-one":2},
        c="acorn";
    a instanceof Array //true
    b instanceof Array //false
    b instanceof Object //true
    c instanceof Array //false 对象C不是引用类型,
    
    • 其实 instanceOf 内部逻辑就是判断 当前引用类型对象的proto 与 目标对象的prototype是否为同一个。从而判断是否为当前对象的实例.先判断当前引用对象的proto是否和目标构造函数的prototype相等,如果不相等在判断引用对象的proto.proto 是否相等,形成一条原型链

    下面两种写法有什么区别?

    //方法1
    function People(name, sex){
        this.name = name;
        this.sex = sex;
        this.printName = function(){
            console.log(this.name);
        }
    }
    var p1 = new People('xiaowei', 2)
    
    //方法2
    function Person(name, sex){
        this.name = name;
        this.sex = sex;
    }
    
    Person.prototype.printName = function(){
        console.log(this.name);
    }
    var p1 = new Person('xiaowei', 2);
    
    • 方法一是直接将方法放在自己的私有空间内,没有放在原型链上,并没有起到公共代码的作用
    • 方法二通过将方法放在原型链上,起到了公共代码的作用,节省了代码量,提升了性能.

    Object.create 有什么作用?

    • Object.create 是什么?
    • Object.create(proto [, propertiesObject ]) 是E5中提出的一种新的对象创建方式,第一个参数是要继承的原型,如果不是一个子函数,可以传一个null,第二个参数是对象的属性描述符,这个参数是可选的。使得后者完全继承前者的属性,前者成为后者的原型。
    • 兼容性:凡实现ECS5标准的浏览器,都能使用,IE9以上
    • 举个例子
    function show(name,age){
      this.name=name;
      this.age=age;
    }
    show.prototype.say=function(){
          console.log("my name is:"+this.name);
    }
    var p=new show("acorn",23);
    var p1=Object.create(p)
    
    • 即创建了一个指向p的原型即show构造函数的p1对象

    hasOwnProperty有什么作用?给出范例

    • hasOwnPerperty是Object.prototype的一个方法,可以判断一个对象是否包含自定义属性而不是原型链上的属性,hasOwnProperty是JavaScript中唯一一个处理属性但是不查找原型链的函数
      范例object.hasOwnProperty(prop)

    如下代码中call的作用是什么?

    function Person(name, sex){
        this.name = name;
        this.sex = sex;
    }
    function Male(name, sex, age){
        Person.call(this, name, sex);    //这里的 call 有什么作用
        this.age = age;
    }
    
    • call调用了Person构造函数,将Person里面的this替换成指向Male构造函数的对象

    补全代码,实现继承

    function Person(name, sex){
        // todo ...
    }
    Person.prototype.getName = function(){
        // todo ...
    };    
    function Male(name, sex, age){
       //todo ...
    }
    //todo ...
    Male.prototype.getAge = function(){
        //todo ...
    };
    var hugner = new Male('xiaoweimei', '男', 2);
    hunger.printName();
    
    function Person(name, sex){
        this.name=name; // todo ...
        this.sex=sex
    }
    Person.prototype.getName = function(){
        console.log(this.name)// todo ...
    };    
    function Male(name, sex, age){
       Person.call(this,name,sex)
       this.age=age //todo ...
    }
    Male.prototype = Object.create(Person.prototype);//todo ...
    Male.prototype.constructor=Male
    Male.prototype.getAge = function(){
        console.log(this.age)//todo ...
    };
    

    相关文章

      网友评论

          本文标题:原型、原型链

          本文链接:https://www.haomeiwen.com/subject/mgbaiqtx.html