文档章节

DOM笔记(十二):又谈原型对象

dwqs
 dwqs
发布于 2014/12/27 11:41
字数 1113
阅读 123
收藏 7
js

因为之前谢过一篇关于原型对象的笔记:浅谈JavaScript中的原型模式。现在我又重新看到这个话题,对原型有了进一步的理解,所以,又要谈谈原型对象。

一、理解原型对象

创建的每一个函数都有一个prototype属性,它指向这个函数的原型对象。利用原型模式创建的方法和属性是被所有实例所共享的。

function Person(){}
Person.prototype.name="dwqs";
Person.prototype.age=20;
Person.prototype.sayName=function()
{
    alert(this.name);
};var per1 = new Person();
per1.sayName();  //dwqsvar per2 = new Person();
per2.sayName();  //dwqsalert(per1.sayName == per2.sayName);  //true

 

默认情况下,prototype指向的原型对象自动获取一个constructor属性,指向prototype属性所在的函数,而原型对象的其它方法和属性均从Object继承。

当调用Person的构造函数创建对象per1和per2时,Person的每个实例(per1和per2)均包含一个指向构造函数(Person)的原型对象的指针。ECMA-262第5版给指针取名为[[Prototype]]。

所以,实例中的指针仅指向原型,而不指向构造函数。虽然没有标准的方法直接访问[[Prototype]]特性,但在DOM笔记(十一)中提供了hasOwnProperty()和isPropertyOf()方法来反应原型对象和实例之间的关系。

//isPrototypeOf(obj)检测obj的[[prototype]]是否指向调用此方法的对象alert(Person.prototype.isPrototypeOf(per1));  //truealert(Person.prototype.isPrototypeOf(per2));  //true

 

hasOwnProperty()则是判断属性是存在原型中还是实例中,只有存在实例中时,才返回true。

per1.blog = "www.ido321.com";
alert(per1.hasOwnProperty("blog"));  //truealert(Person.prototype.hasOwnProperty("blog"));  //falsealert(per1.hasOwnProperty("name"));  //falsealert(Person.prototype.hasOwnProperty("name"));  //true

 

若实例属性和原型属性同名,则同名的原型属性会被屏蔽,但是不会修改原型中的同名属性,当删除同名的实例属性后,又能重新访问被屏蔽的原型属性。

per1.name="i94web";
alert(per1.name);    //i94web,来自实例alert(per2.name);    //dwqs  来自原型delete per1.name;
alert(per1.name);    //dwqs

 

ECMAScript 5提供了Object.getPrototypeOf(obj)来访问obj的[[Prototype]]的指向,即返回obj的原型对象

alert(Object.getPrototypeOf(per1) == Person.prototype);   //true
alert(Object.getPrototypeOf(per1).name);                 //dwqs

 

二、__proto__属性

在IE11、FireFox、Google等现代浏览器中,每个对象支持__proto__(前后都是两个下划线)属性用于访问父类的原型对象。但要注意的是:

1、原型对象应用__proto__属性时,返回当前类的父类的原型对象的引用;当实例对象应用__proto__属性时,返回当前实例所属类的原型对象的引用。

2、Object.prototype.__proto__返回null,Object没有父类。

3、prototype是静态属性,__proto__是实例属性。

//全是truealert(Array.prototype.__proto__ == Object.prototype);
alert((new Array()).__proto__ == Array.prototype);
alert(Person.prototype.__proto__ == Object.prototype);
alert(per1.__proto__ == Person.prototype);
alert(Object.prototype.__proto__ == null);

 

三、重写原型

如果在原型上定义属性或者方法,每次都要将Person.prototype敲一遍,很麻烦。一个简单的方法就是重写原型。

function Person(){}
Person.prototype={
    name:"dwqs",
    age:20,
    sayName:function()
    {
        alert(this.name);
    }
};    
var per1 = new Person();
alert(per1 instanceof Object);  //truealert(per1 instanceof Person);  //truealert(per1.constructor == Object);  //truealert(per1.constructor == Person);  //false

 

因为重写了默认的prototype对象,所以constructor属性指向了新对象的constructor属性(Object构造函数),而不是指向Person了。如果constructor指向很重要,可以重新定义:

function Person(){}
Person.prototype={
    constructor:Person,   //重新定义constructor
    name:"dwqs",
    age:20,
    sayName:function()
    {
        alert(this.name);
    }
};    
var per1 = new Person();
alert(per1.constructor == Person);  //true

 

这样设置之后,constructor的特性[[Enumerable]]是true了(参考DOM笔记(十一)),即可以枚举,默认情况下,该属性不可枚举。

正如前文说的,实例中的指针仅指向原型,而不指向构造函数。所以重写原型对象之后,会切断现有原型和任何之前已经存在的对象实例之间的联系。

[javascript] view plaincopy

  1. <span style="font-size:14px;">function Person(){}  

  2.   

  3. //先创建一个实例  

  4. var per1 = new Person();  

  5.   

  6. //重写原型  

  7. Person.prototype={  

  8. constructor:Person,  

  9. name:“dwqs”,  

  10. age:20,  

  11. sayName:function()  

  12. {  

  13. alert(this.name);  

  14. }  

  15. };  

  16. per1.sayName(); //错误:Uncaught TypeError: undefined is not a function</span>  


重写原型对象之前是这样的:

重写原型对象变成这样了:

四、原生对象的原型

所有原生引用类型,如Object、Array、String等都在其构造函数的原型上定义了方法。在Array.prototype上可以找到sort(),在String.prototype上可以找到substring

alert(typeof Array.prototype.sort);              //functionalert(typeof String.prototype.substring);   //function

 

因此,也可以在原型对象上为引用类型定义新的方法

String.prototype.startWith=function(str)
{    return this.indexOf(str) == 0;
}var msg = "Hello world";
alert(msg.startWith("Hello"));  //true

 

原文首发:http://www.ido321.com/1372.html


© 著作权归作者所有

dwqs
粉丝 3
博文 20
码字总数 24979
作品 0
广州
程序员
私信 提问
《高性能javascript》 笔记

第一部分:关于script 当把js脚本通过script标签放在head中的时候,早期浏览器在遇到script的时候会阻止浏览器加载和渲染html。知道javascript脚本被下载并执行完,且这些javascript是依次下载和...

modernizr
2014/04/03
497
1
javascript笔记总结篇

转载请声明出处 博客原文 随手翻阅以前的学习笔记,顺便整理一下放在这里,方便自己复习,也希望你有也有帮助吧 第一课时 入门基础 知识点: 123456 var a = "iamstring.";var b = 222;var ...

大灰狼的小绵羊哥哥
2018/11/28
0
0
前端面试之JavaScript

1. JS基本的数据类型和引用类型 基本数据类型:number、string、null、undefined、boolean、symbol -- 栈 引用数据类型:object、array、function -- 堆 两种数据类型存储位置不同 原始数据类...

大灰狼的小绵羊哥哥
2018/08/27
0
0
《高性能JavaScript》读书笔记

入手《高性能JavaScript》一周后,终于断断续续看完了。简要说说感受,就是这本书非常薄,非常容易看,认真看的话其实两三个小时就能翻一遍了。这篇文章也是作为一篇阅读笔记,用来记录我在阅...

jrainlau
2017/02/15
0
0
一个demo学会js

全栈工程师开发手册 (作者:栾鹏) 快捷链接: js系列教程1-数组操作全解 js系列教程2-对象和属性全解 js系列教程3-字符串和正则全解 js系列教程4-函数与参数全解 js系列教程5-容器和算法全...

luanpeng825485697
2017/08/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

java通过ServerSocket与Socket实现通信

首先说一下ServerSocket与Socket. 1.ServerSocket ServerSocket是用来监听客户端Socket连接的类,如果没有连接会一直处于等待状态. ServetSocket有三个构造方法: (1) ServerSocket(int port);...

Blueeeeeee
今天
6
0
用 Sphinx 搭建博客时,如何自定义插件?

之前有不少同学看过我的个人博客(http://python-online.cn),也根据我写的教程完成了自己个人站点的搭建。 点此:使用 Python 30分钟 教你快速搭建一个博客 为防有的同学不清楚 Sphinx ,这...

王炳明
昨天
5
0
黑客之道-40本书籍助你快速入门黑客技术免费下载

场景 黑客是一个中文词语,皆源自英文hacker,随着灰鸽子的出现,灰鸽子成为了很多假借黑客名义控制他人电脑的黑客技术,于是出现了“骇客”与"黑客"分家。2012年电影频道节目中心出品的电影...

badaoliumang
昨天
16
0
很遗憾,没有一篇文章能讲清楚线程的生命周期!

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本。 简介 大家都知道线程是有生命周期,但是彤哥可以认真负责地告诉你网上几乎没有一篇文章讲得是完全正确的。 ...

彤哥读源码
昨天
18
0
jquery--DOM操作基础

本文转载于:专业的前端网站➭jquery--DOM操作基础 元素的访问 元素属性操作 获取:attr(name);$("#my").attr("src"); 设置:attr(name,value);$("#myImg").attr("src","images/1.jpg"); ......

前端老手
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部