Javascript中的继承与Prototype

之前学习js仅仅是把w3school上的基本语法看了一次而已,再后来细看书的时候,书中会出现很多很多没有听过的语法,其中一个就是js的继承以及总能看到的prototype。我主要在看的两本js书是《javascript权威指南》,也就是那本犀牛书,还有一本是疯狂xx系列的《疯HTML5/CSS3/Javascript讲义》。前者非常适合用啃js细节,如果需要深入学习一些js内部机制以及相关的内容,这本大块头啃起来还是挺有味道的。后者是本速成教材,可以让你对某个概念有一个非常舒服的打开方式,不晦涩,浅显易懂。大家如果看完w3school之后,感觉没有学到什么东西的话,应该试着去看看书,这是我刚开始学习前端总结出来的小建议。

先说说继承,在js里面其实是没有继承的概念。但大家应该都知道,在面向对象的程序设计里,类之间有显示的继承关系,一个类可以显示地指定继承自哪一个类,然后继承下来的子类就会有父类的属性和方法。js里没有这一概念,但是它一种类似继承的方法来对原来的类进行扩展。这种方式就是通过类的prototype属性,来为类动态增加属性和方法,这种方式类似于继承,但它只能称作是“伪继承”,因为这种继承的实质是修改了原有的类,而不是产生一个子类。

我们先说不用继承的时候,js通过什么样的方法来为对象增加属性和方法呢。

首先,程序为一个对象的并不存在属性进行赋值的时候,就可以认为是为这个对象增加了属性。

【代码01】

                              var obj = {};
                              obj.name = "Jeremy";
                              obj.info = function(){
                                  console.log("This is a method");
                              }

在这里插入说明一下函数、方法、对象还有类的概念理解。

函数,在javascript里面有“一等公民”之称,当在js中定义了一个函数之后,其实就是生成了以下:

1)函数:类似于java的方法,它可以被调用;

2)对象:当定义了一个函数时候,系统也就创建了一个对象,这个对象是Function类的实例;

3)方法:定义了一个函数的时候,这个函数会被附加给某个对象,作为某个对象的方法:

【代码02】

                              function Person(name,gender){
					var val = "valueName";//局部变量
					this.name = name;
					this.gender = gender;
					//定义了一个匿名函数。相当于为Person对象指定了info方法
					this.info = function(){
						console.log("name:"+this.name);
						console.log("gender:"+this.gender);
						console.log("val:"+val);
					}
				}
				var p1 = new Person(‘Jeremy‘,‘male‘);
				//实例p1去调用方法info()
				var v = p1.info();
				console.log("这里能访问到局部变量val:"+v);
 
 
 
4)类:在定义函数的同时,即得到一个和函数同名的类,而这个函数就是该类的构造器,所以在定义一个函数的时候,实际

就是定义了一个构造器

我们来看上面的代码02。

程序定义了一个函数Person,同时也就定义了Person类,函数即类的构造器,这个函数为Person实例p1提供了info方法。

虽然这样我们也完成了对Person的方法增加,但是这样做会存在一些问题。例如性能会低下,每次创建Person对象的时候就会有很多info函数,这样会造成系统内存泄漏(实际是什么情况我暂时没有去探究了),引起性能下降。还有一个很明显的问题,知道js闭包的朋友应该发现了,在info()函数里访问局部变量val,形成了闭包(这里不对闭包展开说了)。然而这会导致val变量的作用域扩大,在代码末尾,程序依旧可以访问到局部变量值。

所以!为了避免这些不好的事情的发生!建议使用prototype属性。

首先在javascript中,每一个javascript对象(null除外)都会和另外一个对象相关联,这个另一个对象就是原型,js中的每一个对象都是从原型那里继承属性。在创建对象的3种方法里面,通过对象直接量创建的对象都具有同一个对象原型,可以通过Object.prototype获得对对象原型的引用。通过关键字new构造函数创建的对象的原型即使构造函数的prototype的值。所以,和使用var empty={};创建对象一样,通过new Object()创建的对象也继承自Object.prototype。

【对象直接量创建对象】即由若干的名/值对组成的映射表。就像这样:

var empty={};//属性为空的对象
var person={name:"gua",age:"18"};//具有name和age属性的值
【new关键字创建对象】通过new关键字创建并初始化一个新的对象。形式上就是new后面跟一个函数调用,这里的函数称作构造函数(constructor),这个
构造函数用于初始化一个新创建的对象。就像这样:
var obj = new Object();
var arr = new Array();
 
 换个好理解一些的说法,就是js对象都是有相同基类(object)的实例。
 
 嗯,我也觉得这一段比较晦涩。
 那来看一下代码是怎么实现的就好了。
 function Person(name,gender){
					this.name = name;
					this.gender = gender;
					//定义了一个匿名函数。相当于为Person对象指定了info方法
					this.info = function(){
						console.log("name:"+this.name);
						console.log("gender:"+this.gender);
					}
				}
				var p1 = new Person(‘Jeremy‘,‘male‘);
				p1.info();
				//为Person类的prototype属性增加了walk函数,即可以认为为Person类动态增加walk实例方法
				Person.prototype.walk = function(){
					console.log(this.name +" 正在散步.......一步一步.....");
				}
				var p2 = new Person(‘Guagua‘,‘female‘);
				p2.info();
				//执行p2的walk方法
				p2.walk();
			        //js已经为类Person动态增加了方法walk,所以p1也具有了walk方法。
				p1.walk();
                

运行结果:

这段程序采用prototype为Person类增加了一个walk方法,这让所有的Person实例共享了一个walk方法,而walk方法并不在Person函数之内,所以就不会产生闭包。

所以我们应该避免使用内嵌函数为类定义方法,使用增加prototype属性的方式来增加方法。

以上是我最近看书学习整理出来的一些内容,有不对的地方望大家指正。

时间: 2024-11-03 22:06:16

Javascript中的继承与Prototype的相关文章

JavaScript学习13 JavaScript中的继承

JavaScript学习13 JavaScript中的继承 继承第一种方式:对象冒充 <script type="text/javascript"> //继承第一种方式:对象冒充 function Parent(username) //父类对象 { this.username = username; //下面的代码最关键的部分就是将子对象的this传递给了父对象 this.sayHello = function() { alert(this.username); } } f

JavaScript中的继承(原型链)

一.原型链 ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 实例1: function SupType() { this.property = true; } SupType.prototype.getSupvalue = function() { return this.property; }; function SubType() { this.subproperty = false; } //原型对象等于一个类型的实例

javascript 中各种继承方式的优缺点 (转)

javascript中实现继承的方式有很多种,一般都是通过原型链和构造函数来实现.下面对各种实现方式进行分析,总结各自的优缺点. 一 原型继承 let Super = functioin(name) { this.name = name; this.setName = (newName) => { this.name = name; }; this.getName = () => { return this.name; } } let Sub = function(sex) { this.se

JavaScript中的继承机制

JavaScript到底是不是面向对象的?! 有人说是,有人说基于对象更准确,因为JavaScript没有类.不去管它,但JavaScript确实提供了一些面向对象的机制. 本文主要讨论JavaScript中的继承.继承,简单来说,就是让子类获得父类的属性和方法,以达到共享和复用的目的. 在开始继承之前,首先需要创建父类.为了后续讨论的需要,我分别为父类创建了私有对象.实例对象.引用对象和两个实例方法. 创建父类的代码如下: // 父类实例的构造函数 function Pet(name,soun

javascript 中实现继承的六种方式

javascript 中对于继承的描述: 许多面向对象语言都支持两种继承的方式:接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.在 javascript 中由于函数没有签名也就无法实现接口继承,而只支持实现继承,而且实现继承主要通过原型链来实现的. 先引述下官方文档对于原型链的描述:其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法.要理解这个概念要先弄清楚构造函数,原型,和实例的关系:每个构造函数(只要是函数)都有一个 prototype 属性该属性指向一

javascript中实现继承的几种方式

javascript中实现继承的几种方式 1.借用构造函数实现继承 function Parent1(){ this.name = "parent1" } function Child1(){ Parent1.call(this); this.type = "child1"; } 缺点:Child1无法继承Parent1的原型对象,并没有真正的实现继承(部分继承) 2.借用原型链实现继承 function Parent2(){ this.name = "p

JavaScript的数据类型都有什么? JavaScript中 toStirng() 与 Object.prototype.toString().call()

JavaScript的数据类型都有什么? (via  BAT互联网公司2014前端笔试面试题:JavaScript篇  http://www.sxt.cn/u/756/blog/4508) 基本数据类型:String,boolean,Number,Undefined, Null 引用数据类型: Object(Array,Date,RegExp,Function) 疑问:这些基本的数据类型的值都是常量,而常量是没有方法的,为什么能够调用方法呢?答案是这样的,五种基本类型除了null.undefin

用实例谈谈javascript中的this和prototype

本文通过几个实例谈谈js中一些基础概念的问题.首先回顾一下js这门语言的特点:除了对象什么都没有.函数在js语言中被看作一种特殊的数据类型,特殊在包含代码并且可以执行,但落点在它是一种数据类型,与数字.字符串等一样.    理解了这个,那么js语言中的全局作用域和函数作用域.全局变量和局部变量.可以通过全局对象和非全局对象划分.如果函数或其他数据类型,不依托非全局变量,那么就默认依托全局变量,即作为全局对象的属性或方法,否则被当作局部对象方法或属性.this被用作指向属性和方法所依托的对象.搞清

关于JavaScript中实现继承,及prototype属性

感谢Mozilla 让我弄懂继承. JavaScript有八种基本类型,函数属于object.所以所有函数都继承自object.//扩展:对象,基本上 JavaScript 里的任何东西都是对象,而且都可以被储存在变量里.将这个记在脑子里. 但是JavaScript并没有真正意义上的继承.而是类似于指向和复制.并且每个函数和对象都有prototype属性.("原型链"(prototype chain)模式) 所有就构造了如同树结构一般的原型链. 常见的几种继承方法: 1. functi