zoukankan      html  css  js  c++  java
  • 原型与原型链

    原型与原型链,这个东西我一直对它很难拿捏,百度查找好多文章,我理解能力查,想要查找一篇文字容易理解,还有代码例子,这样更容易学会

    很幸运发现这篇文章,我来给分享一下

    在javascript这门语言中,原型与原型链是两个重要的概念因为JavaScript是一门给予原型的语言

    在软件设计模式中,有一种模式叫做原型模式,js正式利用这种模式而被创建出来,

    原型模式是什么呢?它是用于创建重复的对象,同时又能保证性能。原型模式的目的是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

    原型:

    原型是一个可以被复制的一个类,通过复制原型可以创建一个一模一样的新对象。通俗来说,原型就是一个模板,在设计语言中更准确的说是一个对象模板

    例子:

    function Person(name){
    
       this.name=name
    
    }
    
    
    Person.prototype.sayHi = function () {
    
    console.log("Hello! I am" + this.name + ".")
    
    }
    
    var joe = new Person("joe") 
    var john = new Person("john")   
    
    joe.sayHi()   //Hello! I am joe.
    john.sayHi()   //Hello! I am john.

    从上面代码可以看出,原型Person定义了一些公用的属性和方法,利用原型创建出来的新对象实例(joe和john对象)会共享原型(Person)的属性和方法

    我们接着看

    var Person = function(name){
        this.name = name;
    }
                
    var joe = new Person("joe");
    var john = new Person("john");
    
    Person.prototype.sayHi = function(){
        console.log("Hello! I am " + this.name + ".");
    }
                
    joe.sayHi();    //Hello! I am joe.
    john.sayHi();   //Hello! I am john.

    这次把新创建的对象(joe和john)提前到原型(Person)的sayHi方法定义之前,并使用严格模式。原型(Person)的sayHi方法依然会被共享出去,所以原型(Person)的属性和方法总是被原型实例所共享

    var Person = function(name){
        this.name = name;
    }
    
    Person.prototype.sayHi = function(){
        console.log("Hello! I am " + this.name + ".");
    }
    
    var joe = new Person("joe");
    var john = new Person("john");
    
    joe.sayHi();    //Hello! I am joe.
    john.sayHi();   //Hello! I am john.
    
    joe.getName = function(){
        console.log(this.name);
    }
    
    joe.getName();    //joe
    john.getName();   //undefined

    这次为新对象实例(joe)添加getName方法,最后只有实例(joe)拥有该方法,而另一个实例(john)并没有getName方法,这说明:通过原型创建的新对选哪个实例是相互独立的,也正是因为这样对象的使用才能更加萤火、更加易于发展

    原型链:

    在js中,所有的对象都拥有一个_proto_属性指向该对象的原型(prototype)。在上面代码中,执行console.log(joe_protp_)后在控制台可以看到输出了原型(Person),然后继续执行console.log(Person._proto_),控制台打印的结果是function(){},为什么Person的原型是function呢?这是因为Person是一个构造函数,它的本质就是一个函数。在js中函数是一等对象

    joe.__proto__  =>  Person,
    
    Person.__proto__  =>  function(){}

    由此可见,原型链记录了原型对象创建的整个过程,因此,我给原型链添加一个概念:原型链是原型对象创建过程的历史记录。

    原型设计带来的问题:

    当查找一个对象的属性时,JavaScript 会根据原型链向上遍历对象的原型,直到找到给定名称的属性为止。直到到达原型链的顶部仍然没有找到指定的属性,就会返回 undefined。

     

    使用 for in 循环可以遍历对象所有的属性,包括该对象在原型链中的属性,如:

    var A = {
        a:1,
        b:2
    };
                    
    var B = Object.create(A);
    var C = Object.create(B);
                
    B.c = 3;
    C.d = 4;
    
    console.log(c)    //{d:4}
                
    for(var key in c){
        console.log(c[key])
    }
    
    //会在控制台中依次打印出4 3 1 2

    注意在控制台中打印的顺序是 4 3 1 2,而不是 1 2 3 4。为什么?因为C的原型是B,B的原型是A。C对象只有一个d属性,执行for...in时先返回C.d,然后在从C的原型(B)中查找到并返回B.c,再从B的原型(A)中查找到并返回A.a和A.b,最后从A的原型(Object)中查找,发现Object中没有任何属性,于是结束for...in。所以最后的结果是 4 3 1 2。这就解释了原型链继承时查找属性的过程是先查找自身属性,当自身属性不存在时,会在原型链中逐级查找。

    有时只需检查对象自身的属性,那么,这种消耗就是一种浪费,怎么解决呢?

    hasOwnProperty 函数:

    hasOwnProperty 函数可以用来检查对象自身是否含有某个属性,返回值是布尔值,当属性不存在时不会向上查找对象原型链。

     

    在上面的代码中添加下面的代码,看看 hasOwnProperty 和 for in 的区别:

    ...
    
    ifvar "a" in C){
        console.log(c["a"]) //属性 a 是原型链上的属性, 输出 1
    }
    
    if(C.hasOwnProperty("a")){
        console.log(c["a"]) //属性 a 不是自身属性,不会执行这一步
    }

    hasOwnProperty 函数只能检查对象是否拥有某个属性,那如何遍历对象的自身属性?

    getOwnPropertyNames 函数:

    getOwnPropertyNames 函数可以获取对象所有的自身属性,返回值是由对象自身属性名称组成的数组,同样不会向上查找对象原型链。

    如:

    console.log(Object.getOwnPropertyNames(C))  //输出 ["d"]

    利用getOwnPropertyNames 函数遍历所有对象所有自身属性,例:

    (fucntion(){
        var
        o = {a:1, b:2},
        propertys = Object.getOwnPropertyNames(o),
        len = propertys.length;
    
        for(var i = 0; i < len; i++){
            var key = propertys[i];
            console.log(o[key])      //输出 1, 2
        }
    })();
  • 相关阅读:
    Server基本语句的用法
    C#本地文件下载以及FTP文件服务下载(以Pdf文件为例)
    一步一步理解AdaBoosting(Adaptive Boosting)算法
    Ubus简单理解
    基于SSL的select编程Linux系统
    SSL协议理解
    802.11r协议理解
    基于MQTT协议的云端proxy远程登陆
    基于mosquitto的MQTT客户端实现C语言
    模拟telnet协议C语言客户端程序
  • 原文地址:https://www.cnblogs.com/0428mm/p/15438856.html
Copyright © 2011-2022 走看看