在我学习与使用javascript三个月中,我一直对javascript的继承关系以及prototype理解不清,导致很多时候为什么这么用说不出个所以然来。截止到本周为止,通过之前的学习以及自己的再学习,自我感觉算是对这一块有了较为清晰的认识,此文将谈谈我对javascript原型与继承的理解,在此之前,我们首先要知道一些基本的知识。

   知识铺垫

  1、数据类型

  JavaScript中的数据类型在曾经我也有提到过,它包括未定义值(undefined),空值(null),布尔值(boolean),数字(number),字符串(string)以及对象(object),而对象中又包含特殊对象数组(array),并且函数也是对象。其中,字符串(string),对象(object)等都是由构造函数来实现的。讲到这里又得说说JavaScript中的函数了。

  2、函数

  就我所知的语言都是有函数这个概念的,所以就不再细说。

  在 JavaScript 中函数也是一个对象,那么对象又是通过什么来创建的呢?对象是作为现有示例(即原型)对象的副本而创建的,该名称就来自于这一概念,此原型对象的任何属性和方法都将显示为从原型的构造函数创建的对象的属性和方法。可以说,这些对象从其原型继承了属性和方法。

  普通的函数与构造函数在JavaScript中都是通过function来创建,不同的是构造函数需要通过大写来标明。例如:

  1. function Person(name, age, sex) {
  2. this.name = name;
  3. this.age = age;
  4. this.sex = sex;
  5. this.say = function () {
  6. console.log('my name is ' + this.name + ",I'm " + this.age )
  7. }
  8. }
  9.  
  10. Person.say_hello = function () {
  11. console.log("Hello,I'm" + this.sex)
  12. };
  13.  
  14. Person.prototype.is_alive = function () {
  15. return true
  16. };
  17.  
  18. var wfsovereign = new Person('wfsovereign', 21, "boy");
  19.  
  20. wfsovereign.say(); //output my name is wfsovereign,I'm 21
  21. console.log(wfsovereign.is_alive()); //output true
  22. console.log(wfsovereign.say_hello(),"----"); //output undefined

  此例中,创建了构造函数Person,接受参数为name,age,拥有静态方法say_hello(),实例方法say()和is_alive(),使用构造函数创建实例对象wfsovereign,能够调用实例方法,调用静态方法时提示未定义。

  在构造函数后通过"."来添加的方法或属性,称之为静态方法或静态属性,这是实例之后的对象不能访问的。因此,我们通过wfsovereign调用say_hello()时才会提示undefined。

  那么,我们写在构造函数的prototype上的方法is_alive()为什么实例过后仍然能够被访问呢?这个问题我们先放放,先来看看实例对象与构造函数间的联系,通过控制台,我们输出

  1. console.log(wfsovereign.prototype);
  2. console.log(wfsovereign.__proto__);
  3. console.log(wfsovereign.constructor);

  可以看到

  1. undefined //wfsovereign.prototype
  2.  
  3. Person {is_alive: function} //wfsovereign.__proto__)
  4. constructor: function Person(name, age, sex) {
  5. is_alive: function () {
  6. __proto__: Object
  7.  
  8. function Person(name, age, sex) { //wfsovereign.constructor
  9. this.name = name;
  10. this.age = age;
  11. this.sex = sex;
  12. this.say = function () {
  13. console.log('my name is ' + this.name + ",I'm " + this.age )
  14. }
  15. }

  可以看到,实例对象wfsovereign没有prototype属性,但是有了指向构造函数Person.prototype的__proto__属性以及指向构造函数的constructor属性,而Person这一构造函数也有指向object的__proto__属性,说明Person也是通过object创建的一个实例。这个时候我相信聪明如你就能回答上面提出的问题了—我们写在构造函数的prototype上的方法is_alive()为什么实例过后仍然能够被访问呢?

  由此,我们得出,创建的每一个函数都有prototype属性,这是一个指针,它指向一个对象,这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。也就是说prototype是通过调用构造函数而创建的那个对象实例的原型对象,并且只有函数才有prototype属性,实例的对象没有该属性,即这里用Person创建的实例wfsovereign是没有prototype这一属性的。

  当使用构造函数(Person)创建一个实例(wfsovereign)的时候,实例内部将包含一个内部指针(__proto__)指向构造函数的prototype,这个连接存在于实例和构造函数的prototype之间,而不是实例与构造函数之间,实例与构造函数之间通过constructor连接。知道了prototype是什么和怎么来的之后,我们再来看JavaScript的原型链就容易多了。

   继承与原型链

  1、原型链的理解

  JavaScript 不包含传统的类继承模型,而是使用 prototype 原型模型。在JavaScript中,一共有两种类型的值,原始值和对象值。每个对象都有一个内部属性 prototype ,我们通常称之为原型。原型的值可以是一个对象,也可以是null。如果它的值是一个对象,则这个对象也一定有自己的原型。当从一个对象那里调取属性或方法时,如果该对象自身不存在这样的属性或方法,就会自己去关联的prototype对象那里寻找,如果prototype没有,就会去关联的创造者那里找,直到prototype为undefined为止,Object的prototype就是undefined即所有原型都终止于 Object.prototype,这样就形成了一条线性的链,我们称之为原型链。JavaScript正是通过原型链来调用关联创造者的属性与方法的即继承。

  2、使用原型的好处

  可以让对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中添加定义对象信息,而是可以直接将这些信息添加到原型中,通过指针引用的方式来调用。使用构造函数的主要问题就是每个方法都要在每个实例中创建一遍。

  

ps:本文内容若是有误或者迷糊,还请指正或指出。

浅谈系列之 javascript原型与对象的更多相关文章

  1. javaScript系列 [03]-javaScript原型对象

    [03]-javaScript原型对象 引用: javaScript是一门基于原型的语言,它允许对象通过原型链引用另一个对象来构建对象中的复杂性,JavaScript使用原型链这种机制来实现动态代理. ...

  2. 浅谈JS中的原型对象和原型链

    我们知道原型是一个对象,其他对象可以用它实现属性继承,除了prototype,又有__proto__ 1. prototype和__proto__的区别 prototype是函数才有的属性      ...

  3. 浅谈模块化的JavaScript

    模块化JavaScript之风早已席卷而来, CommonJS . AMD . NodeJS .RequireJS . SeaJS . curljs  等模块化的JavaScript概念及库扑面而来, ...

  4. JavaScript 原型和对象创建底层原理

    1. prototype/__proto__/constructor JS原型链和继承网上已经烂大街了,5毛可以买一堆,这里只提一下: constructor:普通对象和函数对象都有,指向创建它的函数 ...

  5. 浅谈 ECMAScript 和 JavaScript

    ES5与ES3基本保持兼容,较大的语法修正和新功能加入,将由JavaScript.next完成. 什么是ECMAScript?http://baike.baidu.com/link?url=G1T8n ...

  6. 浅谈Java和JavaScript中变量和数据类型的区别

    对于一门编程语言的学习,如果第一步是安装环境,那么第二步一定是学习这门语言的基本规则,变量和数据类型则首当其冲 JavaScipt作为一个蹭Java热度而命名的语言,在很多方面和Java也有一定的相似 ...

  7. 浅谈ListBox控件,将对象封装在listBox中,在ListBox中显示对象中某个属性,在ListBox中移除和移动信息

    大家好,俗称万事开头难,不经历风雨,怎能见彩虹.在此小编给大家带来一个自己练习的小实例,希望与大家一起分享与交流.下面进入应用场景,从SQL2008数据库取出数据,给ListBox赋值在界面并显示出来 ...

  8. 浅谈Java虚拟机内存中的对象创建,内存布局,访问定位

    参考于 深入理解Java虚拟机 这里介绍HotSpot虚拟机(自带的虚拟机) 1.对象的创建 对于程序员来说,创建对象的方法: User user1 = new User(); User user2 ...

  9. 安卓开发_浅谈Fragment之事务添加Fragment对象

    我们都知道给一个activity动态添加fragment的时候 有下面几种添加方式 看一下布局文件 <LinearLayout xmlns:android="http://schema ...

随机推荐

  1. Mapreduce的文件和hbase共同输入

    Mapreduce的文件和hbase共同输入 package duogemap;   import java.io.IOException;   import org.apache.hadoop.co ...

  2. Unity3d学习 预设体(prefab)的一些理解

    之前一直在想如果要在Unity3d上创建很多个具有相同结构的对象,是如何做的,后来查了相关资料发现预设体可以解决这个问题! 预设体的概念: 组件的集合体 , 预制物体可以实例化成游戏对象. 创建预设体 ...

  3. Linux 添加新磁盘,在线扩充空间

    CentOS 7开发环境中的home 目录空间满了,需要增加空间 到虚拟机上执行"ls /sys/class/scsi_host",然后重新扫描SCSI总线来添加设备.如右图.然后 ...

  4. PHP中遍历XML之SimpleXML

    简单来讲述一些XML吧,XML是可扩展标记语言,是一种用于标记电子文件使其具有结构性的标记语言.XML是当今用于传输数据的两大工具之一,另外一个是json. 我们在PHP中使用XML也是用来传输数据, ...

  5. 多线程条件通行工具——CountDownLatch

    CountDownLatch的作用是,线程进入等待后,需要计数器达到0才能通行. CountDownLatch(int)构造方法,指定初始计数. await()等待计数减至0. await(long, ...

  6. 文档对象模型DOM通俗讲解

    转自:http://www.jb51.net/article/42671.htm 在开始之前先说一点,DOM是非常容易理解的,但是大家说的太官方,让人很是难于理解,我们就用非常简单的语言翻译一遍.加深 ...

  7. windows 7(32/64位)GHO安装指南(U盘制作篇)~

    本篇接着上篇的介绍,为同学讲解U盘启动盘的制作.虽然本篇大白菜的官网上也有类似的教程,但是为了完整性,我将在这里为大家细细的讲解.在这里说一下,系统包和软件包的下载大家可以自行下载,很简单的,小主就不 ...

  8. keepalived从机接管后主机恢复不抢占VIP

    在lvs+keepalived环境中,为了减小keepalived主从切换带来的意外风险,,设置主机恢复后不抢占VIP.待进行vrrp协议通告备机不可用时切换.主要修改两个地方.(红色部分) 只需修改 ...

  9. [css]实现垂直居中水平居中的几种方式

    转自博客 http://blog.csdn.net/freshlover/article/details/11579669 居中方式: 一.容器内(Within Container) 内容块的父容器设 ...

  10. 机器指令翻译成 JavaScript —— No.4 动态跳转

    上一篇,我们用模拟流程的方式,解决了跳转问题. 不过静态跳转,好歹事先是知道来龙去脉的.而动态跳转,只有运行时才知道要去哪.既然流程都是未知的,翻译从何谈起? 动态跳转,平时出现的多吗?非常多!除了 ...