在我学习与使用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. 关于Unity3D自定义编辑器的学习

    被人物编辑器折腾了一个月,最终还是交了点成品上去(还要很多优化都还么做).  刚接手这项工作时觉得没概念,没想法,不知道.后来就去看<<Unity5.X从入门到精通>>中有关于 ...

  2. 关于微软HttpClient使用,避免踩坑

    最近公司对于WebApi的场景使用也越来越加大了,随之而来就是Api的客户端工具我们使用哪个?我们最常用的估计就是HttpClient,在微软类库中命名空间地址:System.Net.Http,是一个 ...

  3. WPF 微信 MVVM 【续】修复部分用户无法获取列表

    看过我WPF 微信 MVVM这篇文章的朋友,应该知道我里面提到了我有一个小号是无法获取列表的,始终也没找到原因. 前两天经过GitHub上h4dex大神的指导,知道了原因,是因为微信在登录以后,web ...

  4. [C#] 剖析 AssemblyInfo.cs - 了解常用的特性 Attribute

    剖析 AssemblyInfo.cs - 了解常用的特性 Attribute [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5944391.html 序 ...

  5. Ajax实现原理,代码封装

    都知道实现页面的异步操作需要使用Ajax,那么Ajax到是怎么实现异步操作的呢? 首先需要认识一个对象 --> XMLHttpRequest 对象 --> Ajax的核心.它有许多的属性和 ...

  6. FullCalendar日历插件说明文档

    FullCalendar提供了丰富的属性设置和方法调用,开发者可以根据FullCalendar提供的API快速完成一个日历日程的开发,本文将FullCalendar的常用属性和方法.回调函数等整理成中 ...

  7. 【Java每日一题】20170105

    20170104问题解析请点击今日问题下方的"[Java每日一题]20170105"查看(问题解析在公众号首发,公众号ID:weknow619) package Jan2017; ...

  8. 《动手实现一个网页加载进度loading》

    loading随处可见,比如一个app经常会有下拉刷新,上拉加载的功能,在刷新和加载的过程中为了让用户感知到 load 的过程,我们会使用一些过渡动画来表达.最常见的比如"转圈圈" ...

  9. Apache Cordova开发Android应用程序——番外篇

    很多天之前就安装了visual studio community 2015,今天闲着么事想试一下Apache Cordova,用它来开发跨平台App.在这之前需要配置N多东西,这里找到了一篇MS官方文 ...

  10. Android的Kotlin秘方(I):OnGlobalLayoutListener

    春节后,又重新“开张”.各位高手请继续支持.谢谢! 原文标题:Kotlin recipes for Android (I): OnGlobalLayoutListener 原文链接:http://an ...