js面试笔试–prototype详解

js面试笔试–prototype详解对JavaScript中原型模式的理解一:什么是原型对象?有什么优点?   简单的来说,无论何时,我们创建的每一个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,这个对象包含了通过调用该构造函数所创建的对象共享的属性和方法。其实我们平常的叫法就是指:prototype就是通过该构造函数创建的某个实例的原型对象,但是其实prototype是每个构造函数的属性而已,只能说…

大家好,又见面了,我是你们的朋友全栈君。

对JavaScript中原型模式的理解

一:什么是原型对象?有什么优点? 
   简单的来说,无论何时,我们创建的每一个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,这个对象包含了通过调用该构造函数所创建的对象共享的属性和方法。其实我们平常的叫法就是指:prototype就是通过该构造函数创建的某个实例的原型对象,但是其实prototype是每个构造函数的属性而已,只能说万物皆对象罢了。 
   原型对象的优点是:所有的对象实例都可以共享它包含的属性和方法。这一点可以在构造函数里就可以看出来,因为构造函数在函数里面就定义了对象的实例信息,而原型对象可以在任何地方定义属性和方法。例如:

function Person(){}
Person.prototype.name = 'bangbang';
Person.prototype.age = 18;
Person.prototype.job = 'programmer';
Person.prototype.dream = function(){
    console.log('Change yourself');
}

var person1 = new Person();
person1.dream();    //Change yourself

var person2 = new Person();
person2.dream();
//判断两个实例继承的方法和属性是否全等
console.log(person1.dream === person2.dream);
console.log(person1.age === person2.age);
  •  

由以上的代码可以看出它比构造函数方法的好处就是,person1和person2访问的都是同一个dream()函数,即他们的属性和方法都是共享的。 
二:深入理解原型对象和prototype? 
  由上面可知,我们创建了一个函数,就会根据ECMAscript特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针。就像前面的例子,Person.prototype.constructor指向Person,而通过这个构造函数,我们还可以继续为原型对象添加其他属性和方法。 
  下面,我们就开始从原理上说明上面代码运行机制的: 
1. 创建一个自定义的构造函数后,它的原型对象默认只会有constructor属性,其他属性和方法都是从Object继承而来的; 
2. 当调用构造函数创建一个新实例后,该实例的内部将包含一个指针,指向构造函数的原型对象。ECMA5中称这个指针叫[[prototype]]。虽然在脚本中没有标准的方式访问[[prototype]],但Firefox、Safari和Chrome在每个对象上都支持一个属性proto;而在其他浏览器中,这个属性则是完全不可见的。不过要明确的真正一点就是,这个连接存在于 实例 和 构造函数的原型对象 之间,而不是存在于实例和构造函数之间,用前面使用Person构造函数和Person.prototype创建实例的代码为例,各个对象之间的关系如下图所示: 
这里写图片描述 
  上图展示了Person构造函数、Person的原型以及Person现有的两个实例之间的关系,再次,Person.prototype指向了原型对象,而Person.prototype.constructor又指回了Person。原型对象中除了包含constructor属性之外,还包括后来添加的其他属性。Person的每个实例——person1和person2都包含一个内部属性,该属性指向了Person.prototype;换句话说,他们与构造函数没有直接关系。 
  注意:虽然这两个实例都不包含属性和方法,但我们却可以调用name、age、job、dream()方法和属性,这是通过查找对象属性的过程来实现的。 
  虽然我们不能访问到[[prototype]],但可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系。因为这两个实例都有一个指向Person.prototype的指针,因此,都返回true如下所示:

console.log(Person.prototype.isPrototypeOf(person1));//true
console.log(Person.prototype.isPrototypeOf(person2));//true
  •  

ECMA5增加了一个方法,叫Object.getPrototypeOf(),这个方法返回[[Prototype]]的值,也就是括号里面对象的原型,例如:

console.log(Object.getPrototypeOf(person1) == Person.prototype; // true
console.log(Object.getPrototypeOf(person1).name); //'bangbang'
  •  

用hasOwnProperty()方法可以检测一个属性是存在于实例中还是原型中。还是上面的例子:

console.log(person1.hasOwnProperty('name'); //false
person1.name = 'qiqi';
console.log(person1.hasOwnProperty('name'); //true —— 来自实例
console.log(person1.name);  //'qiqi' ——来自实例
delete person1.name;
console.log(person1.name); //'bangbang' —— 来自原型
console.log(person1.hasOwnProperty('name'); //true ——来自原型
  •  

当我们为person1添加name属性的时候,如下图图所示: 
这里写图片描述 
三:组合使用构造函数模式和原型模式优点最多: 
  以上我讲述了用构造函数生成对象的原理以及生成的对象和原型对象之间的关系,原理了解了这么多,我么当然需要知道怎么在合适的时候用他们。创建自定义类型的最常见方式就是组合使用构造函数模式和原型模式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。每个实例都会有自己的一份实例属性的副本,但同时又共享着对方发的引用,最大限度的节省了内存。如下例所示:

        function Person(name,age,job){
            this.name = name;
            this.age = age;
            this.job = job;
            this.love = ['qiqi','lili'];
        }
        Person.prototype = {
            constructor : Person,
            dream : function(){
                console.log(this.love[0]);
            }
        }
        var person1 = new Person('bangbang',18,'programmer');
        var person2 = new Person('xiaoya',18,'teacher');
        console.log(person1.love);
        console.log(person2.love)
        console.log(person1.love === person2.love);  //false
        //给person1的love属性添加元素
        person1.love.push('niuniu');
        console.log(person1.love)  //["qiqi", "lili", "niuniu"]
        console.log(person2.love)  //["qiqi", "lili"]
        console.log(person1.love === person2.love);  //false
        console.log(person1.dream === person2.dream);//true
  •  

以上这种模式是ECMAscript中使用最广泛的,认同度最高的,优点最多的创建自定义类型的方法,也就是创建JavaScript中类的方法。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/163394.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • Redis雪崩效应的解决方案(转)[通俗易懂]

    Redis雪崩效应的解决方案(转)[通俗易懂]1、可以使用分布式锁单机版的话本地锁当突然有大量请求到数据库服务器时候,进行请求限制。使用所的机制,保证只有一个线程(请求)操作。否则进行排队等待(集群分布式锁,单机本地锁)。减少服务器吞吐量,效率低。保证只能有一个线程进入实际上只能有一个请求在执行查询操作也可以在此处进行使用限流的策略~2、缓存标记publicobjectGetProductListNew()…

  • xp的终极优化

    xp的终极优化总体设想:让WinXP更苗条、性感、速度更快,使用更便捷。为了达到这个目的,我们主要从四个方面入手:1、减少磁盘空间占用2、终止不常用的系统服务3、安全问题4、另外一些技巧首先问一下,你是不是很想激活XP,不。。。准确的说你是不是想在ms的站上能够升级。如果答案是肯定的话,那我们就先来探讨一下安装的问题,目前流行的V4、V5、V6版本我还是比较推荐的,尤其是V5和V6这两个。安装的过程中有个序

  • lambda表达式python_Python中的Lambda表达式「建议收藏」

    lambda表达式python_Python中的Lambda表达式「建议收藏」Lambda表达式在python程序中是一种很常见的匿名方法的书写形式,它书写起来非常简单,但是牺牲了可读性。下面来看一下Lambda的简单介绍。语法lambda[parameter_list]:expressionLambda表达式的返回值是一个函数,[parameter_list]是函数的参数,expression是具体的操作。它对应的非匿名方法的书写方式为:deffunction([par…

    2022年10月17日
  • mysql 索引类型以及使用场景[通俗易懂]

    mysql 索引类型以及使用场景[通俗易懂] 关于MySQL索引的好处,如果正确合理设计并且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。对于没有索引的表,单表查询可能几十万数据就是瓶颈,而通常大型网站单日就可能会产生几十万甚至几百万的数据,没有索引查询会变的非常缓慢。还是以WordPress来说,其多个数据表都会对经常被查询的字段添加索引,比如wp_comments表中针对5个字段设计了B…

  • Java邮箱正则表达式验证_java正则表达式以什么开头

    Java邮箱正则表达式验证_java正则表达式以什么开头packagecom.Janson.test;/***@authorJanson*/importjava.util.regex.*;publicclasstest{publicstaticbooleancheckEmaile(Stringemaile){/***正则表达式实用规则…

  • Unix操作系统常用命令「建议收藏」

    Unix操作系统常用命令「建议收藏」Unix操作系统常用命令一、关于档案/目录处理的命令1、ls——列目录这是最基本的档案指令。ls的意义为”list”,也就是将某一个目录或是某一个档案的内容显示出来。格式:ls-1ACFLRabcdfgilmnopqrstux-W[sv][files]ls的常用参数如下:-a:在UNIX中若一个目录或文件名字的第一个字符为…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号