JS 学习笔记--12---面向对象
练习中使用的浏览器为IE10,如果各位朋友有不同意见或者本文有什么错误地方,望指正
ECMASCript有两种开发模式:函数式(面向过程)和面向对象。面向对象有一个很明显的标志,那就是类,我们可以通过类来创建很多具有相同的属性和方法的对象。但是ECMAScript中没有类的概念,它和其他很多的面向对象的高级语言中的面向对象不一样。
1、创建对象方式一
通过以前的var obj=new Object()方式来创建一个对象,是可以的,但是如果我们想创建两个或者多个相同属性或者方法对象的时候,势必会造成很多的代码,故这种方式不可取
这种方式创建对象的时候,添加属性的时候必须要通过 对象名.属性名 的方式来增加属性,添加方法也是同样的,不过方法体可以声明为一个匿名方法,然后赋值给一个属性,方法中可以用this来代替对象obj,因为this代表的是当前的作用域所属的对象,也就是前面new出来的Obejct()
// 传统的声明对象的方法,声明了两个长得差不多的对象,box,box2
var box=new Object(); //创建一个对象
box.user='abc'; //给对象添加属性
box.age=22;
box.run=function(){ //给对象添加方法,
return this.user+" "+this.age+" "+"运行中。。。";//this表示当前作用域下的对象
} // this 表示 new Object()实例化出来的那个对象
// this 要放在一个作用域下面,比如上面的box.run(){},这个是box对象作用域下的方法,方可用this,来表示box本身 alert(box.user); //abc
alert(box.run()); //abc 22 运行中。。。
alert(box instanceof Object); //true var box2=new Object(); //创建第二个对象
box2.user='jack'; //添加属性
box2.age='33';
box2.run=function(){ //添加方法
return this.user+" "+this.age+" "+"运行中。。。";//this表示当前作用域下的对象,即box2
} alert(box2.user); //jack
alert(box2.run()); //jack 33 运行中。。。
alert(box2 instanceof Object); //true
2、工厂模式创建对象
为解决上面问题而出现了工厂模式,这种方法就是为了解决实例化对象的时候产生大量的重复的代码的问题,创建方式如下:
// 模试
function createObject(user,age){
var obj=new Object(); //创建一个新的对象,每调用一次就创建一次
obj.user=user; //给每个创建属性
obj.age=age;
obj.run=function(){ //this 就是指的当前创建的这个对象,obj
return this.user+" " +this.age+" "+"运行中...";
}
return obj; //需要返回这个对象,返回的是对象的引用
} //由模式创建变量 少了很多代码
var box1=createObject('abc',22); //创建对象box1
var box2=createObject('jack',33); //创建对象box2 alert(box1.run()); //abc 22 运行中... 运行对象box1的run方法
alert(box2.run()); //jack 33 运行中... 运行对象box2的run方法
上面写了一个工厂模式,并且创建了一个对象,以后就可以调用这个对象的方法和属性了,但是这种方法还有一个问题就是,当有多个工厂模式,多个不同的类型的对象的时候,是无法判断具体是那个类型的实例对象
// 模式2 内容中和模式1有一点小区别
function createObject2(user,age){
var obj=new Object();
obj.user=user;
obj.age=age+'a';
obj.run=function(){
return this.user+" " +this.age+" "+"运行中...";
}
return obj;
}
//由工程模式2创建的对象,
var box3=createObject2('tom',44); //用模式2创建对象box3
alert(box3.run()); //tom 44a 运行中... 运行对象box3的run方法 //判断三个变量结果都是object类型 但无法判断是那个工厂模式创建的
alert(box1 instanceof Object); //true
alert(box2 instanceof Object); //true
alert(box3 instanceof Object); //true //不管怎样,他们都是Object类型,就无法区分,谁到底是谁的对象了
如果用同一个模式创建了两个对象的话,即使赋初值是一样的,但是他们并不相等,因为他们是引用类型的,而且里面的方法也是引用类型的
alert(box1.run);//均返回的是上面创建的时候=后面的内容
alert(box2.run); alert(box1==box2); //false 比较的是他们的引用,说明这是两个对象
3、构造函数初始化
ECMAScript 中可以通过构造函数(构造方法)的方式来创建对象,类似于Object对象,创建方式如下:
//定义了一个构造函数一
function Box(user,age){
this.user=user; //用构造函数创建的时候,后台会自动的创建一个对象,this就指向了这个对象
this.age=age; //由于是后台自动的创建,故不需要显示的new一个对象,而且用this代替对象名
this.run=function(){
return this.user+" "+this.age+" "+'运行中...';
} //构造函数创建的时候,是不需要显示返回的,后台会自动的返回他引用
} //用构造函数创建对象
var box1 = new Box('abc',22); //用构造函数创建对象,需要通过方式:new 构造函数名(参数表)
var box2 = new Box('jack',33); //运行两个对象的方法
alert(box1.run()); // abc 22 运行中...
alert(window.box1.run()); // abc 22 运行中...
alert(box2.run()); // jack 33 运行中...
从上面可以看出,其实和C#等高级语言中的类差不多,构造函数中写同样的类容,外面创建变量的时候通过 new 构造函数名(参数)【高级语言中构造函数和类同名】。
在用构造函数创建对象的时候,每当我们用new关键字来创建一个对象的时候,执行过程如下:
1)、当使用了构造函数,并且 new 构造函数() 的时候,后台就执行了new Object() 语句;
2)、将构造函数的作用域给了新的对象,(就是new Object() 出来的对象),而函数中的this就代表了刚刚创建出来的这个对象;
3)、执行构造函数中的代码;后台返回这个新对象的引用,后台直接返回
和工厂模式相比不同:
1)、我们省略了var obj=new Object(); 这一显示的实例化一个对象;
2)、在添加属性和方法的时候用直接赋值给了this对象,即this来代替了工厂模式中的对象名;
3)、没有了return语句,即不需要我们手动的将创建的这个对象进行返回,系统会自动的返回这个对象的引用
使用构造函数的时候遵循的一些规范:
1)、构造函数也是函数,但是构造函数名最好是大写开头(有助于和普通函数进行区别);
2)、使用构造函数创建对象的时候,必须通过 new 构造函数名(参数值) 来创建对象
用构造函数创建的对象解决了工厂模式中遗留的问题,就是已经能够判断变量是由那个类型[构造函数]实例化而来的,因为用instanceof来判读对象的时候,可以将构造函数名Box当做类型来处理,故能够判断出实例对象是由那个构造函数类型实例化而来
//构造函数二
function Box2(user,age){
this.user=user;
this.age=age;
this.run=function(){
return this.user+","+this.age+",运行中..."
}
} var box3 = new Box2('tom',44); //判断对象的类型 可以知道是通过什么构造函数来创建的对象,变量时那个对象的引用
alert(box1 instanceof Object); //true
alert(box1 instanceof Box); //true 知道是用构造函数1来创建的对象
alert(box2 instanceof Object); //true
alert(box2 instanceof Box); //true
alert(box3 instanceof Object); //true
alert(box3 instanceof Box2); //true 知道是用构造函数2来创建的对象,box3是Box2对象的引用
关于构造函数中的this:在全局中this代表的是window对象,在构造函数体内,this代表的就是当前构造函数声明的对象
构造函数和普通函数的唯一区别就在于他们的调用方式不同,只不过构造函数也是函数,必须使用 new 运算符来调用才能够创建一个对象,否则就是普通的函数
构造函数里面的方法返回的也是引用,当我们创建两个对象,传递相同的参数的时候,两个对象是不相等的,同时box1.run==box2.run [run是构造函数中定义的一个方法]的返回结果也是false,即方法是引用,具有唯一性的。既然是引用在创建方法的时候是可以用Functon类型来创建,即:this.run=new Function("return ...");这种方法来创建,但是这是没有必要的
//下面两个执行的结果是一样的
alert(box1.run); //返回的是整个函数体 包括关键字 function
alert(box2.run); //返回的是整个函数体 包括关键字 function alert(box1.run==box2.run); //false 它们的返回值一样,但是不相等 因为他们比较的是引用 //既然构造函数中的方法是引用,也就是说可以写成this.run= new Function("this.user+this.age+'运行中...'");的形式,但是这样没有多少意义
通过构造函数外面绑定同一个函数的方法来保证引用地址的一致性,因为这个方法是在外面创建的,只是创建了一次,即构造函数中使用 this.run=run; 后面这run是在全局中定义的一个方法。这样使用了全局的函数 run()来解决了保证引用地址一致的问题,但这种方式又带来了一个新的问题,全局中的 this 在对象调用的时候是 Box 本身,而当作普通函数调用的时候,this 又代表 window。故完全没有必要这样,而且不利于代码的封装
//构造函数二
function Box2(user,age){
this.user=user;
this.age=age;
this.run=run;
} function run(){
return this.user+" "+this.age+" " +'运行中...';
} var box=new Box2('abc',22);
alert(box.run()); // abc 22 运行中...
冒充调用:可以再外面定义一个Object类型,或者其他类型的变量,然后通过冒充调用来获取构造函数中声明的属性和方法,即通过prototype属性中的call和apply方法;
var o=new Object();
Box.call(o,'maochong',55); //通过对象冒充的行试来获取这个对象的所有方法和属性
alert(o.user); //maochong
alert(o.run()); //maochong 55 运行中...
这样,虽然对象o是Object类型的变量,但是由于冒充调用改变了它的作用域,它就具有构造函数Box中定义的所有的方法和属性
JS 学习笔记--12---面向对象的更多相关文章
- JS 学习笔记 (七) 面向对象编程OOP
1.前言 创建对象有很多种方法,最常见的是字面量创建和new Object()创建.但是在需要创建多个相同结构的对象时,这两种方法就不太方便了. 如:创建多个学生信息的对象 let tom = { n ...
- JS学习笔记2_面向对象
1.对象的定义 ECMAScript中,对象是一个无序属性集,这里的“属性”可以是基本值.对象或者函数 2.数据属性与访问器属性 数据属性即有值的属性,可以设置属性只读.不可删除.不可枚举等等 访问器 ...
- 《JavaScript高级程序设计》学习笔记12篇
写在前面: 这12篇博文不是给人看的,而是用来查的,忘记了什么基础知识,点开页面Ctrl + F关键字就好了 P.S.如果在对应分类里没有找到,麻烦告诉我,以便尽快添上.当然,我也会时不时地添点遗漏的 ...
- Python3+Selenium3+webdriver学习笔记12(js操作应用:滚动条 日历 内嵌div)
#!/usr/bin/env python# -*- coding:utf-8 -*-'''Selenium3+webdriver学习笔记12(js操作应用:滚动条 日历 内嵌div)'''from ...
- ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则
ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- 一点感悟:《Node.js学习笔记》star数突破1000+
写作背景 笔者前年开始撰写的<Node.js学习笔记> github star 数突破了1000,算是个里程碑吧. 从第一次提交(2016.11.03)到现在,1年半过去了.突然有些感慨, ...
- WebGL three.js学习笔记 6种类型的纹理介绍及应用
WebGL three.js学习笔记 6种类型的纹理介绍及应用 本文所使用到的demo演示: 高光贴图Demo演示 反光效果Demo演示(因为是加载的模型,所以速度会慢) (一)普通纹理 计算机图形学 ...
- Node.js学习笔记(2):基本模块
Node.js学习笔记(2):基本模块 模块 引入模块 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式.在No ...
- Vue.js学习笔记(2)vue-router
vue中vue-router的使用:
随机推荐
- SqlServer存储过程学习笔记(增删改查)
* IDENT_CURRENT 返回为任何会话和任何作用域中的特定表最后生成的标识值. CREATE PROCEDURE [dbo].[PR_NewsAffiche_AddNewsEntity] ( ...
- 如何在Word表格中的某一栏添加背景颜色
如何在Word表格中的某一栏添加背景颜色 编写人:CC阿爸 2014-3-14 用鼠标选中某一个单元格然后右键单击 下拉菜单选择.<边框和低纹>然后点<低纹>选项卡 选中色卡 ...
- 分析MapReduce执行过程
分析MapReduce执行过程 MapReduce运行的时候,会通过Mapper运行的任务读取HDFS中的数据文件,然后调用自己的方法,处理数据,最后输出. Reducer任务会接收Mapper任务输 ...
- ThinkPHP实现联动菜单;
联动菜单,首先给你看看前端是怎么写的:
- 魅族MX3问题集锦
我第一台智能机已经服役2年半了,已经满足不了现在日益庞大的APP,所以打算让他光荣退役.我觉得IPhone仍然是目前做的最好的手机,但是对于我来说好像没什么必要,尤其那土豪般的价格.而且我平时看视频居 ...
- java中4中类修饰符访问范围
public:本类中可见,同包中可见,子类中可见,其他包中可见. protected:本类中可见,同包中可见,子类中可见,其他包不可见. 默认:本类中可见,同包中可见,子类不可见,其他包不可见. pr ...
- xtrabackup之Innobackupex全备恢复
一.当前环境 [mysql@hadoop1 ~]$ mysql --defaults-/my.cnf -uroot -p123456 -P3306 mysql> show variables l ...
- Mongodb 3.0 创建用户
MongoDB 3.0 安全权限访问控制,在添加用户上面3.0版本和之前的版本有很大的区别,这里就说明下3.0的添加用户的方法. 创建第一个用户(该用户需要有grant权限,即:账号管理的授权权限) ...
- 避免url传值字符串sjstr过长,使用from表单【隐藏域】post提交
1.普通的url传值<html--------------- <!-- 隐藏域post提交url --> <form id="urlPost" action ...
- MAC 重置MySQL root 密码
重置MySQL root 密码:当忘记密码,或者想要强行重置 MySQL 密码的时候,可以像下面这样: 1.停止 MySQL 服务 sudo /usr/local/mysql/support-file ...