资讯专栏INFORMATION COLUMN

这篇文章, 让你了解 JavaScript 中的原型(基础篇-图文)

ityouknow / 1525人阅读

摘要:返回一个布尔值,指示指定的对象是否位于调用此方法的对象的原型链中。

JavaScript - Prototype

JavaScript是一门动态语言, 你可以在任何时候向对象上添加属性,如下

    function Student() {
        this.name = "LeBron James";
        this.gender = "Male";
    }

    var studObj1 = new Student();
    studObj1.age = 15;
    alert(studObj1.age); // 15

    var studObj2 = new Student();
    alert(studObj2.age); // undefined

正如上面的实例, age 属性附加在 studObj1 实例上. 然而 studObj2 实例没有这个属性, 因为 age 属性只在 studObj1 实例上定义了.

那么, 如果想在后期添加一个属性且能被所有的实例所共享, 该怎么办? 答案这就今天主角 Prototype.

Prototype 是一个对象, 默认情况下与JavaScript中的任何一个函数或对象有关, 只是唯一区别在于函数的prototype 属性是可访问可修改的,而对象prototype属性是不可见的.

默认情况下任何一个函数包含 Prototype 对象, 如下图:


prototype 对象是一种特殊类型的可枚举对象, 可以将需要附加属添加到其上,这些属性将在其构造函数的所有实例之间共享。

因此, 把上面的示例中使用函数的 prototype 来添加属性,以便于所有对象中都可以访问到, 如下:

    function Student() {
        this.name = "LeBron James";
        this.gender = "M";
    }

    Student.prototype.age = 15;

    var studObj1 = new Student();
    alert(studObj1.age); // 15

    var studObj2 = new Student();
    alert(studObj2.age); // 15

使用 字面量 或 通过 new关键字和构造函数 的方式创建的每一个对象都包含 __proto__ 属性, 该属性指向创建此对象的函数的 原型对象.

你可以在谷歌和火狐开发者调试工具中查看该属性(__proto__) , 根据下面的示例:

    function Student() {
        this.name = "LeBron James";
        this.gender = "M";
    }

    var studObj = new Student();

    console.log(Student.prototype); // object
    console.log(studObj.prototype); // undefined
    console.log(studObj.__proto__); // object

    console.log(typeof Student.prototype); // object
    console.log(typeof studObj.__proto__); // object

    console.log(Student.prototype === studObj.__proto__ ); // true

正如上面例子看到, 函数通过 [[函数名称]].prototype 方式访问到原型对象. 但是, 对象(实例)并没有暴露出 prototype 属性,而是使用 __proto__ 来访问它.

Object 对象的原型

前面提及到, 原型对象在对象中是不可见. 使用 Object.getPrototypeOf(obj) 方法来访问实例的原型对象. (这也是推荐方式, __proto__ 并不是标准属性, 在IE11以下其它浏览器中没有实现).

    function Student() {
        this.name = "LeBron James";
        this.gender = "M";
    }

    var studObj = new Student();

    Student.prototype.sayHi= function(){
        alert("Hi");
    };

    var studObj1 = new Student();
    var proto = Object.getPrototypeOf(studObj1);  
    // returns Student"s prototype object
                
    alert(proto.constructor); 
    // returns Student function 

Object 原型对象包含如下 属性方法

属性 描述
constructor 返回创建该实例的构造函数
__proto__ 指向创建该实例的构造函数的原型对象.
方法 描述
hasOwnProperty() 返回一个布尔值,指示对象是否包含指定的属性作为该对象的直接属性,而不是通过原型链继承。
isPrototypeOf() 返回一个布尔值,指示指定的对象是否位于调用此方法的对象的原型链中。
propertyIsEnumerable() 返回一个布尔值,该布尔值指示指定的属性是否可枚举。
toLocaleString() 返回本地格式的字符串.
toString() 返回对象字符串形式.
valueOf() 返回指定对象的原始值.

Chrome 和 Firfox 将对象的原型表示为 __proto__, 而内部引用为 [[Prototype]]. IE不支持,只有IE11包含它.

修改原型

如上所述, 每个对象都能链接到函数的原型对象. 如果您更改了函数的原型, 则只有新对象将链接到更改后的原型. 所有其他现有对象仍然链接到旧的函数原型. 下面实例来演示这个场景:

    function Student() {
        this.name = "LeBron James";
        this.gender = "M";
    }

    Student.prototype.age = 15;

    var studObj1 = new Student();
    alert("studObj1.age = " + studObj1.age); // 15

    var studObj2 = new Student();
    alert("studObj2.age = " + studObj2.age); // 15

    Student.prototype = { age : 20 };

    var studObj3 = new Student();
    alert("studObj3.age = " + studObj3.age); // 20

    alert("studObj1.age = " + studObj1.age); // 15
    alert("studObj2.age = " + studObj2.age); // 15
使用原型

原型对象被JavaScript引擎用来做两件事:

查找对象的属性和方法

在JavaScript中实现继承

    function Student() {
        this.name = "LeBron James";
        this.gender = "M";
    }

    Student.prototype.sayHi = function(){
        alert("Hi");
    };

    var studObj = new Student();
    studObj.toString();

在上面的示例, toString() 方法在 Student 中没有定义, 那么它是如何以及从哪里找到 toString() 的呢?

在这里,原型出现了. 首先, JavaScript 引擎检查 studObj 是否存在 toString 方法?. 如果没有找到,那么它使用 studObj__proto__ 链接指向 Student函数原型对象. 如果它仍然无法找到它那么它会在往上层并检查 Object 函数的原型对象,因为所有对象都是从 JavaScript 中的 Object 派生的,并查找 toString() 方法. 因此, 它在Object函数的原型对象中找到 toString() 方法,因此我们可以调用 studObj.toString().

查找方式,如下图所示

上述就是原型基本知识点以及应用.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105362.html

相关文章

  • 查漏补缺 - 收藏集 - 掘金

    摘要:酝酿许久之后,笔者准备接下来撰写前端面试题系列文章,内容涵盖浏览器框架分钟搞定常用基础知识前端掘金基础智商划重点在实际开发中,已经非常普及了。 这道题--致敬各位10年阿里的前端开发 - 掘金很巧合,我在认识了两位同是10年工作经验的阿里前端开发小伙伴,不但要向前辈学习,我有时候还会选择另一种方法逗逗他们,拿了网上一道经典面试题,可能我连去阿里面试的机会都没有,但是我感受到了一次面试1...

    YuboonaZhang 评论0 收藏0
  • 前端相关大杂烩

    摘要:希望帮助更多的前端爱好者学习。前端开发者指南作者科迪林黎,由前端大师倾情赞助。翻译最佳实践译者张捷沪江前端开发工程师当你问起有关与时,老司机们首先就会告诉你其实是个没有网络请求功能的库。 前端基础面试题(JS部分) 前端基础面试题(JS部分) 学习 React.js 比你想象的要简单 原文地址:Learning React.js is easier than you think 原文作...

    fuyi501 评论0 收藏0
  • JavasScript重难点知识

    摘要:忍者级别的函数操作对于什么是匿名函数,这里就不做过多介绍了。我们需要知道的是,对于而言,匿名函数是一个很重要且具有逻辑性的特性。通常,匿名函数的使用情况是创建一个供以后使用的函数。 JS 中的递归 递归, 递归基础, 斐波那契数列, 使用递归方式深拷贝, 自定义事件添加 这一次,彻底弄懂 JavaScript 执行机制 本文的目的就是要保证你彻底弄懂javascript的执行机制,如果...

    forsigner 评论0 收藏0
  • 个人分享--web前端学习资源分享

    摘要:前言月份开始出没社区,现在差不多月了,按照工作的说法,就是差不多过了三个月的试用期,准备转正了一般来说,差不多到了转正的时候,会进行总结或者分享会议那么今天我就把看过的一些学习资源主要是博客,博文推荐分享给大家。 1.前言 6月份开始出没社区,现在差不多9月了,按照工作的说法,就是差不多过了三个月的试用期,准备转正了!一般来说,差不多到了转正的时候,会进行总结或者分享会议!那么今天我就...

    sherlock221 评论0 收藏0

发表评论

0条评论

ityouknow

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<