javascript OOP(上)(八)
一、OOP的概念和继承
1、OOP概念
面向对象程序设计(Object-oriented programming,OOP)是一种程序设计范型,同时也是一种程序开发的方法。对象指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。
OOP特点:继承、封装、多态和抽象。
2、基于原型的继承
function Foo(){
this.y=2;
} /*每个函数对象有一个对象属性prototype,这个prototype是个对象,Fooj就是Foo.prototype*/ Foo.prototype.x=1;
var obj3=new Foo();
/*创建一个Foo的实例obj3,
使用new调用的时候,Foo作为构造器来使用,并且this指向一个对象,而这个对象的原型会指向构造器的prototype属性,也就是Foo.prototype*/ console.log(obj3.y); //2 对象上的
console.log(obj3.x); //1 原型上的
3、prototype属性与原型
用函数声明创建一个空函数function Foo(){}的时候,函数就会有一个prototype对象属性。
prototype对象属性默认会有2个属性,一个是constructor,会指向它本身Foo;另外一个是_proto_,一般的对象都会指向Object.prototype。
x:1是通过赋值语句Foo.prototype.x=1;增加的。
Foo.prototype的作用:
当使用new Foo去构造Foo的实例的时候,这个prototype属性会用作new出来的对象(obj1,obj2,obj3...)的原型(_proto_)。
prototype:是函数对象上面预设的对象属性。
_proto_:对象上的原型,通常都是它的构造器的prototype属性。
4、更复杂的实例:
Student继承Person
<script>
function Person(name,age){//new方法调用,this作为 return值
this.name=name;
this.age=age;
}
/*Person.prototype添加实例共享的属性和方法*/
Person.prototype.hi=function(){
console.log('Hi,my name is'+this.name+"I'm"+this.age+"years old now.");
} Person.prototype.LEGS_NUM=2;
Person.prototype.ARMS_NUM=2;
Person.prototype.walk=function(){
console.log(this.name+" is wlking...");
}
/*初始化Student类*/
function Student(name,age,className) {
Person.call(this,name,age);//先调用父类初始化
this.className=className;
} /*继承*/
Student.prototype=Object.create(Person.prototype);
Student.prototype.constructor=Student;
/*覆盖基类的hi方法*/
Student.prototype.hi=function(){
console.log('Hi,my name is '+this.name+",I'm "+this.age+" years old now,and from "+this.className+'.');
} Student.prototype.learn=function(subject){
console.log(this.name+' is learning '+subject+' at '+this.className+'.');
}
//test
var bosn=new Student('Bosn',27,'Class 3,Grade 2');
console.log(bosn.hi());//Hi,my name is Bosn,I'm 27 years old now,and from Class 3,Grade 2.
console.log(bosn.LEGS_NUM);//
bosn.walk();
//Bosn is wlking...
bosn.learn('math');
//Bosn is learning math at Class 3,Grade 2.
</script>
二、原型链
如下:
从后往前:
bosn构造:通过 new Student()创建了bosn实例,bosn实例的原型_proto_指向构造器的prototype属性,也就是Student.prototyep。Studnet.prototype上面有hi()方法和learn()方法。
Studnet.prototype构造:通过Object.create(Person.prototype)来构造。Student.prototype是个空对象,这个空对象随后添加了hi()方法和learn()方法,它的原型_proto_指向了Person.prototype。
Person.prototype:直接定义了一个Person函数,在Person.ptototype上添加了共享的属性和方法,这个Person.prototype就是一个内置的普通对象。它本身也会有原型就是Object.prototype。
坑1:
并不是所有的对象,最终原型链上都有Object.prototype。
通过Object.create(null)创建的对象原型链上没有Object.prototype,也就没有Object.prototype上的方法。
坑2:
并不是所有的函数对象都会有prototype属性。
ES5的bind()函数用来修改函数在运行时的this。
bind方法返回的也是一个函数,可以通过typeof判断一下,但是bind()方法返回的函数就没有prototype属性。
三、prototype属性
1、prototype相关的修改
/*给prototype添加属性和方法会影响到已创建或新创建的实例*/
Student.prototype.x=101;
console.log(bosn.x); // /*修改prototype并不会影响已经创建的实例,会影响后续创建的实例*/
Student.prototype={y:2};
console.log(bosn.y); //undefined
console.log(bosn.x); // var nunnly=new Student('Nunnly',3,'Class LOL KengB');
console.log(nunnly.x); //undefined
console.log(nunnly.y); //
2、内置的构造器的prototype
内置的函数构造器也有prototype属性,比如Object,Number,Boolean,Function,等等。
bind,apply,call等等都是从Function的prototype上取到的。
边际效应:
修改这些构造器的prototype有时候会带来一些边际效应。
Object.prototype.x=1;
var obj={};
console.log(obj.x); //
for(var key in obj){
console.log('result: '+key);
}
//result: x
边际效应:在prototype上添加属性x,在for in遍历的时候会把x遍历出来。
解决办法:
ES5里面有defineProperty来控制对象属性。默认标签都是false,下面只设置writable:true。简洁表示不可枚举,也不可配置。
Object.defineProperty(Object.prototype,'x',
{writable:true,value:1});
var obj={};
console.log(obj.x); //
for(var key in obj){
console.log('result: '+key);
}
//nothing output here
这样for in的时候就不会有边际效应。所以如果写nodejs,判断一下如果有defineProperty,可以通过这种方式来改写Object.property这样一些内置构造器上的prototype的时候,可以跨过这样一个边际效应。
很少会用到修改Object.prototype,因为影响范围太广了。 但是有时候为了兼容性可能会通过Object.defineProperty做一些ES5才支持的方法模拟。
四、实现继承的方式
见代码。
<script>
function Person(){
}
function Student(){
} Student.prototype=Person.prototype;//1 禁止用,改变Student也会修改Person Student.prototype=new Person();//2
/*可以实现,问题:比如构造函数有一个name和age,new Person()的时候name和age传什么呢?传任何东西都是很奇怪的。因为Student只是一个类,还没有实例化。 所以这里只是为了继承调用了Person的构造函数,创建了一个实例,在很多情况下也是比较奇怪的。
*/
Student.prototype=Object.create(Person.prototype);//
Student.prototype.constructor=Person; /*第三种是相对理想的办法*/
/*
创建了一个空的对象,并且对象的原型指向了Person.prototype。既保证了继承Person.prototype删的方法,并且Student.prototype又有自己的一个空的对象,Student.prototype的修改又不会影响Person.prototype。
*/ /*Object.create是ES5才支持的方法,在ES5之前可以模拟实现*/
if(!Object.create){
Object.create=function(proto){
function F(){};
F.prototype=proto;
return new F; /*new调用时创建一个对象,并且原型指向F.prototype,即proto*/
}
}
</script>
本文作者starof,因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处:http://www.cnblogs.com/starof/p/4904929.html有问题欢迎与我讨论,共同进步。
javascript OOP(上)(八)的更多相关文章
- Javascript多线程引擎(八)
Javascript多线程引擎(八) Javascript 多线程项目, 做到现在已经快3个月了(加上前期准备编译原理和必要的文档), 该项目(js-engine)已经快进入尾声了, 现在该引擎 ...
- 使用JavaScript OOP特性搭建Web应用
最近,我面试了一个有五年 Web 应用程序开发经验的软件开发人员.四年半来她一直在从事 JavaScript 相关的工作,她自认为 JavaScript 技能非常好,但在不久之后我就发现实际上她对 J ...
- 几款极好的 JavaScript 文件上传插件
文件上传功能作为网页重要的组成部分,几乎无处不在,从简单的单个文件上传到复杂的批量上传.拖放上传,需要开发者花费大量的时间和精力去处理,以期实现好用的上传功能.这篇文章向大家推荐几款很棒的 JavaS ...
- JavaScript返回上一页代码区别
JavaScript返回上一页代码区别: window.history.go(-1); //返回上一页 window.history.back(); //返回上一页 //如果要强行刷新的话就是:win ...
- 【精心推荐】几款极好的 JavaScript 文件上传插件
文件上传功能作为网页重要的组成部分,几乎无处不在,从简单的单个文件上传到复杂的批量上传.拖放上传,需要开发者花费大量的时间和精力去处理,以期实现好用的上传功能.这篇文章向大家推荐几款很棒的 JavaS ...
- AGS API for JavaScript 图表上地图
原文:AGS API for JavaScript 图表上地图 图1 图2 图3 -------------------------------------华丽丽的分割线--------------- ...
- JavaScript: 世界上最被误解的语言|Douglas Crockford
JavaScript: 世界上最被误解的语言 JavaScript: The Wrrrld's Most Misunderstood Programming Language Douglas Croc ...
- jQuery UI 是建立在 jQuery JavaScript 库上的一组用户界面交互、特效、小部件及主题
jQuery UI 是建立在 jQuery JavaScript 库上的一组用户界面交互.特效.小部件及主题.无论您是创建高度交互的 Web 应用程序还是仅仅向窗体控件添加一个日期选择器,jQuery ...
- JavaScript OOP 之 this指向
今天给大家分享一个JavaScript OOP中关于分辨this指向对象的小技巧,很实用呦! 我们先来看一段代码: 大家能判断出func();和obj.func();这两句的this指向吗? 首先,我 ...
- JavaScript返回上一页和返回上一级页面并刷新
JavaScript返回上一页和刷新当前页 window.history.go(-1); //返回上一页 window.history.back(); //返回上一页 //如果要强行刷新的话就是:wi ...
随机推荐
- Alpha 冲刺 (3/10)
目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:冲刺3 团队部分 后敬甲(组长) 过去两天完成了哪些任务 文字描述 组织第一次团队编程 继续阅读小程序开发文档 接下来的 ...
- Spring学习(十八)Bean 的三种依赖注入方式介绍
依赖注入:让调用类对某一接口实现类的依赖关系由第三方注入,以移除调用类对某一接口实现类的依赖.接下来将详细的向大家介绍Spring容器支持的三种依赖注入的方式以及具体配置方法:• 属性注入方法• ...
- 003_crlf注入漏洞
一. (1) 线上收到一个crlf 注入的漏洞. 同时启用80和443才会暴露,配置如下: server { listen 80; listen 443 ssl; server_name www.jy ...
- matlab积分使用
clc; %清屏 clear; %清除变量 close all; %关闭 syms x; f(x) = x; df = int(f(x),x);%求不定积分 figure; subplot(1,2,1 ...
- 无备份mysql删除表后恢复
mysql从5.6.17开始自动设置innodb_file_per_table为on,每个表设置单独表空间,数据不是集中存放在ibdata1里.下面测试下无备份后drop表后的恢复. 前奏生成数据字典 ...
- HTML 页面meta标签
1. 概述 1.1 说明 <meta>标签提供了HTML文档的元数据[元数据(Metadata)是数据的数据信息],即页面的元信息,元数据不会显示在客户端,但是会被浏览器解析.meta元素 ...
- STM32L476应用开发之二:模拟量数据采集
采集模拟量数据在一台一起中是必不可少的功能.在本次实验中我们要采集的模拟量值主要包括氧气传感器的输出以及压力变送器的输出. 1硬件设计 我们需要采集数据对精度有一定的要求,而STM32L476自带AD ...
- Spark Streaming 实现思路与模块概述
一.基于 Spark 做 Spark Streaming 的思路 Spark Streaming 与 Spark Core 的关系可以用下面的经典部件图来表述: 在本节,我们先探讨一下基于 Spark ...
- maven添加镜像与常用配置
maven解压后conf文件夹有个 settings.xml 在这个文件中可以配置我们的maven 配置镜像: 找到<mirrors></mirrors>找到这个节点在节点中添 ...
- 编辑技巧之如何跟PDF文档添加贝茨编号
除了office办公软件,pdf文档现在使用的频率也便多了,不论是工作或是学习,阅读都用阅读器打开就行了,可是如果想要修改.编辑那只用阅读器是无法进行编辑的,其实PDF文件的编辑还是很方便,使用PDF ...