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

   知识铺垫

  1、数据类型

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

  2、函数

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

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

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

 function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.say = function () {
console.log('my name is ' + this.name + ",I'm " + this.age )
}
} Person.say_hello = function () {
console.log("Hello,I'm" + this.sex)
}; Person.prototype.is_alive = function () {
return true
}; var wfsovereign = new Person('wfsovereign', 21, "boy"); wfsovereign.say(); //output my name is wfsovereign,I'm 21
console.log(wfsovereign.is_alive()); //output true
console.log(wfsovereign.say_hello(),"----"); //output undefined

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

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

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

 console.log(wfsovereign.prototype);
console.log(wfsovereign.__proto__);
console.log(wfsovereign.constructor);

  可以看到

 undefined    //wfsovereign.prototype

 Person {is_alive: function}    //wfsovereign.__proto__)
constructor: function Person(name, age, sex) {
is_alive: function () {
__proto__: Object function Person(name, age, sex) { //wfsovereign.constructor
this.name = name;
this.age = age;
this.sex = sex;
this.say = function () {
console.log('my name is ' + this.name + ",I'm " + this.age )
}
}

  可以看到,实例对象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. UE4新手之编程指南

    虚幻引擎4为程序员提供了两套工具集,可共同使用来加速开发的工作流程. 新的游戏类.Slate和Canvas用户接口元素以及编辑器功能可以使用C++语言来编写,并且在使用Visual Studio 或 ...

  2. 从0开始搭建SQL Server AlwaysOn 第一篇(配置域控)

    从0开始搭建SQL Server AlwaysOn 第一篇(配置域控) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://www.cnb ...

  3. Emoji选项列表

    一.需要的前提文件 从网上下载Emoji的表情包,当然是png的图片,因为WPF不支持彩色的Emoji,所以,做列表的时候,需要用图片. 随着压缩包一起的还有一个Emoji.xml文件,文件的层级结构 ...

  4. 15个关于Chrome的开发必备小技巧[译]

    谷歌Chrome,是当前最流行且被众多web开发人员使用的浏览器.最快六周就更新发布一次以及伴随着它不断强大的开发组件,使得Chrome成为你必备的开发工具.例如,在线编辑CSS,console以及d ...

  5. 利用Node.js的Net模块实现一个命令行多人聊天室

    1.net模块基本API 要使用Node.js的net模块实现一个命令行聊天室,就必须先了解NET模块的API使用.NET模块API分为两大类:Server和Socket类.工厂方法. Server类 ...

  6. hadoop2.7之Mapper/reducer源码分析

    一切从示例程序开始: 示例程序 Hadoop2.7 提供的示例程序WordCount.java package org.apache.hadoop.examples; import java.io.I ...

  7. spring的BeanFactory加载过程

    ApplicationContext spring = new ClassPathXmlApplicationContext("classpath*:spring/applicationCo ...

  8. 学习笔记:7z在delphi的应用

    最近做个发邮件的功能,需要将日志文件通过邮件发送回来用于分析,但是日志文件可能会超级大,测算下来一天可能会有800M的大小.所以压缩是不可避免了,delphi中的默认压缩算法整了半天不太好使,就看了看 ...

  9. 为Xamarin更好的开发而改写的库

    欢迎大家加入以下开源社区 Xamarin-Cn:https://github.com/Xamarin-Cn Mvvmcross-Cn:https://github.com/Mvvmcross-Cn  ...

  10. 写给.NET开发者的数据库Migration方案

    微软给我们提供了一种非常好用的数据库迁移方案,但是我发现周围的同学用的并不多,所以我还是想把这个方案整理一下..NET选手看过来,特别是还在通过手工执行脚本来迁移数据库的同学们,当然你也可以选择EF的 ...