zoukankan      html  css  js  c++  java
  • JS中的原型和原型链

    JS中的原型和原型链
    讲原型的时候,我们应该先要记住以下几个要点,这几个要点是理解原型的关键:

    1、所有的引用类型(数组、函数、对象)可以自由扩展属性(除null以外)。

    2、所有的引用类型都有一个’_ _ proto_ _'属性(也叫隐式原型,它是一个普通的对象)(理解感觉用于存储他的父类的原型)

    3、所有的函数都有一个’prototype’属性(这也叫显式原型,它也是一个普通的对象)(理解为对象所拥有的是有对象,可以用来存储子类公共的方法)

    4、所有引用类型,它的’_ _ proto_ _'属性指向它的构造函数的’prototype’属性。

    5、当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它的’_ _ proto_ _'属性(也就是它的构造函数的’prototype’属性)中去寻找。

    那么要点说完了,我们就根据这些要点来理解原型和原型链。

    原型

    我们先来看一个原型的例子。

            //这是一个构造函数
            function Foo(name,age){
                this.name=name;
                this.age=age;
            }
            /*根据要点3,所有的函数都有一个prototype属性,这个属性是一个对象
            再根据要点1,所有的对象可以自由扩展属性
            于是就有了以下写法*/
            Foo.prototype={
                // prototype对象里面又有其他的属性
                showName:function(){
                    console.log("I'm "+this.name);//this是什么要看执行的时候谁调用了这个函数
                },
                showAge:function(){
                    console.log("And I'm "+this.age);//this是什么要看执行的时候谁调用了这个函数
                }
            }
            var fn=new Foo('小明',19)
            /*当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它
            构造函数的'prototype'属性中去找*/
            fn.showName(); //I'm 小明
            fn.showAge(); //And I'm 19

    这就是原型,很好理解。那为什么要使用原型呢?

    试想如果我们要通过Foo()来创建很多很多个对象,如果我们是这样子写的话:

        function Foo(name,age){
                this.name=name;
                this.age=age;
                this.showName=function(){
                    console.log("I'm "+this.name);
                }
                this.showAge=function(){
                    console.log("And I'm "+this.age);
                }
            }

    那么我们创建出来的每一个对象,里面都有showName和showAge方法,这样就会占用很多的资源。
    而通过原型来实现的话,只需要在构造函数里面给属性赋值,而把方法写在Foo.prototype属性(这个属性是唯一的)里面。这样每个对象都可以使用prototype属性里面的showName、showAge方法,并且节省了不少的资源。

    感觉有点像java继承关系,类似子类通过peototype向父类中定义一些公共的方法(不知道理解的对不对)!!

    原型链
    理解了原型,那么原型链就更好理解了。

    #####下面这段话可以帮助理解原型链
    根据要点5,当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它构造函数的’prototype’属性中去寻找。那又因为’prototype’属性是一个对象,所以它也有一个’_ _ proto_ _'属性。

    那么我们来看一个例子:

            // 构造函数
            function Foo(name,age){
                 this.name=name;
                 this.age=age;
            }
            Object.prototype.toString=function(){
                //this是什么要看执行的时候谁调用了这个函数。
                console.log("I'm "+this.name+" And I'm "+this.age);
            }
            var fn=new Foo('小明',19);
            fn.toString(); //I'm 小明 And I'm 19
            console.log(fn.toString===Foo.prototype.__proto__.toString); //true
            
            console.log(fn.__proto__ ===Foo.prototype)//true
            console.log(Foo.prototype.__proto__===Object.prototype)//true
            console.log(Object.prototype.__proto__===null)//true
    是不是觉得有点奇怪?我们来分析一下。

    首先,fn的构造函数是Foo()。所以:
    fn._ _ proto _ _=== Foo.prototype

    (理解为fn的引用原型 === Foo的prototype对象)
    又因为Foo.prototype是一个普通的对象,它的构造函数是Object,所以:
    Foo.prototype._ _ proto _ _=== Object.prototype

    (理解为Foo的引用原型 === Object的prototype对象)
    通过上面的代码,我们知道这个toString()方法是在Object.prototype里面的,当调用这个对象的本身并不存在的方法时,它会一层一层地往上去找,一直到null为止。


    所以当fn调用toString()时,JS发现fn中没有这个方法,于是它就去Foo.prototype中去找,发现还是没有这个方法,然后就去Object.prototype中去找,找到了,就调用Object.prototype中的toString()方法。


    这就是原型链,fn能够调用Object.prototype中的方法正是因为存在原型链的机制。

    另外,在使用原型的时候,一般推荐将需要扩展的方法写在构造函数的prototype属性中,避免写在_ _ proto _ _属性里面。

    原文链接:https://blog.csdn.net/qq_36996271/java/article/details/82527256

  • 相关阅读:
    微人事项目-mybatis-持久层
    通过外键连接多个表
    springioc
    Redis 消息中间件 ServiceStack.Redis 轻量级
    深度数据对接 链接服务器 数据传输
    sqlserver 抓取所有执行语句 SQL语句分析 死锁 抓取
    sqlserver 索引优化 CPU占用过高 执行分析 服务器检查
    sql server 远程备份 bak 删除
    冒泡排序
    多线程 异步 beginInvoke EndInvoke 使用
  • 原文地址:https://www.cnblogs.com/lzghyh/p/12957497.html
Copyright © 2011-2022 走看看