Javascript中的类

类是对象的模板,用于创建共享一系列属性和方法的类似对象。

使用new关键字调用函数,可以创建对象实例。

 function Accommodation(){};

 var house = new Accommodation();

 var apartment = new Accommodation();

同一模板的对象实例之间互无关联,这些对象实例是完全独立的变量,只不过共享同一个模板结构而已。

类的扩充:

1.找出对象的构造器

通过new关键字创建的对象的实例,有一个额外的属性:constructor,该属性指向创建该对象时所使用的JavaScript构造函数。

 house.constructor === Accommodation;//true

 apartment.constructor === Accommodation;//true

关键字instanceof也可以检查对象是否是某个构造函数的实例。

house instanceof Accommodation;

apartment instanceof Accommmodation;

2.通过原型添加属性和方法

Javascript中的每个函数(构造器)都有一个叫prototype的属性,这个属性指向一个对象,我们用关键字new来创建一个“类”的对象实例时,实例中包含的属性和方法都来自prototype所指向的这个对象。

//定义构造函数
function Accommodation(){} //为这个类添加属性
Accommodation.prototype.floors = 0;
Accommodation.prototype.rooms = 0;
Accommodation.prototype.sharedEntrance = false; //为这个类添加方法
Accommodation.prototype.lock = function(){};
Accommodation.prototype.unlock = function(){}; //创建对象实例
var house = new Accommodation();
var apartment = new Accommodation(); //读取对象实例的属性
console.log(house.floors);//
console.log(apartment.rooms);// //修改对象属性的值
house.floors = 2;
apartment.sharedEntrance = true; //调用对象实例的方法
house.unlock();
apartment.lock();

prototype属性本身是一个对象,这个对象被关联在扮演“类”这个角色的函数身上,因此,还可以用对象直接量标记法为构造函数添加属性和方法。

//定义构造函数
function Accommodation(){} //为这个类添加属性和方法
Accommodation.prototype = {
floors: 0,
rooms: 0,
sharedEntrance: false,
lock: function(){},
unlock: function(){}
}

prototype这个关键字有一个强大的特性:允许在对象实例已经被创建后继续添加属性和方法,新增属性和方法会自动添加到所有对象实例中,不管是已创建的还是将要创建的。

3.通过作用域添加属性和方法

javascript函数体内定义的变量和函数,作用域都限于函数体内,在该函数体外无法访问这些变量和函数——对这些函数和变量来说,包裹他们的外层函数提供了一个沙箱般的编程环境,或者说一个闭包。

4.上下文和this关键字

javascript中this关键字代表的是一个函数的上下文环境,这个上下文环境大多数情况下指的是函数运行时封装这个函数的那个对象。

//在所有函数之外,this表示的是全局window对象
console.log(this === window);//true //因为doSomething函数在对象外部被调用,this指向的是浏览器中的window对象
function doSomething(){
console.log(this === window); //true
} doSomething(); var house = {
floors: 2,
isLocked = false,
lock: function(){
console.log(this === house);//true 因为this关键字代表的是包含这个方法的那个对象
//也可以把this看做house对象的替身,可以使用点标记法
this.isLocked = true;
},
} house.lock();
console.log(house.isLocked);//true

对象中的嵌套函数其上下文环境是全局的window对象,而非包含它的那个对象。但我们可以在this指向包含这个函数的对象时,将this的值保存在一个变量中,在用到该对象时用这个变量代替。

var apartment = {
islocked: false,
lock: function(){
var that = this;
//设置isLocked属性
this.isLocked = true;
function doSomething(){
console.log(this === apartment);//false
console.log(this === window);//false
console.log(that === apartment);//false
//通过that变量来修改apartment对象的isLocked属性
that.isLocked = false;
}
doSomething();
},
} apartment.lock(); console.log(apartment.isLocked);//false

在使用new关键字创建对象时,this指向的值和一般情况下又有区别,这种情况下this指向的是通过构造函数所创建的那个对象实例。也因为这个特性,得以在构造函数中通过this来设置所有对象实例的属性和方法,而非像之前那样使用prototype关键字。

//定义一个新的构造函数来表示一种住宅
function Accommodation(){
//this关键字指向的是通过这个“类”创建的对象实例
this.floors = 0;
this.rooms = 0;
this.sharedEntrance = false;
this.isLocked = false;
this.lock = function(){
//函数中的this一般指向包含函数的那个对象,本例中的this指向的是创建的对象实例,因为这个函数是通过这个被创建的对象实例来调用的
this.isLocked = true;
};
this.unlock = function(){
this.isLocked = false;
}
} //通过构造函数来创建对象实例
var house = new Accommodation();
var apartment = new Accommodation(); //读取和修改属性值,调用方法等操作都和普通对象一样
console.log(house.floors);
house.floors = 2;
apartment.lock();

开发者一般会结合使用prototype和this关键字来定义对象实例的属性和方法,其中前者用来定义方法,后者用来定义属性。每次通过构造器创建一个新的对象实例,构造函数都会被执行一次。之所以结合使用这两个关键字,是为了避免每次初始化一个对象实例时都要执行那些对方法进行初始化的代码。通过prototype关键字定义的方法只需定义一次,然后就可以为所有通过这个构造函数创建的对象所用,这使得对象的创建变得更加高效;

开发者们喜欢在构造函数中使用this关键字来设置属性的另一个原因是可以给构造函数传递参数,这样我们就能在调用构造函数时通过传递参数来对某些属性进行初始化了。

我们也可以向构造函数传递一个对象直接量作为唯一的参数,这个对象直接量包含了进行属性设置所需的所有初始值。

5.方法的链式调用

要实现链式调用,只需在“类”中的每个方法最后通过this关键字返回对象实例的引用即可。

6.继承

传统编程语言的一项关键功能就是可以创建一些新的类来继承或者扩展某个父类的属性和方法,这些新的类和该父类都有某种类似的逻辑关联,这些新的类被称为子类。

Javascript中也可以实现这种继承,不过是通过Javascript的原型链来实现,被称为原型继承。

//定义一个有两个方法的类
function Accommodation(){} Accommodation.prototype.lock = function(){}
Accommodation.prototype.unlock = function(){} //定义一个构造函数,它将成为我们的子类
function House(defaults) {
defaults = defaults || {};
//将本类所有实例的floors属性初始化为2
this.floors = 2; this.rooms = defaults.rooms ||7;
} //将House类的原型设为Accommodation“类”的一个实例,使用关键字new来调用Accommodation的构造函数,这样就能创建并返回一个包含所有属性和方法的对象。这个对象被传递给House"类"的原型,这样House"类"就得以继承Accommodation 的所有内容
House.prototype = new Accommodation(); //对象实例的constructor属性指向创建该对象的那个构造函数,然而由于House继承了Accommodation的所有内容,constructor值也被复制了,所以我们现在需要重设constructor值,使其指向新的子类。如果没有这一步,通过House"类"创建的对象就会报告说他们是通过Accommodation“类”创建的。
House.prototype.constructor = House;

封装:

当通过继承对已有的类进行改变或特殊化时,父类的所有属性和方法对子类都是可用的,在子类中不需要额外声明或定义任何东西就能使用父类的属性和方法,这种特性被称为封装。子类之需要定义那些在父类基础上新增的属性和方法即可;

多态:

在构造一个新的子类来继承并扩展一个“类”的时候,你可能需要将某个方法替换为一个同名的新方法,新方法和原方法功能类似,但对子类做出了针对性的改变,这就是多态,Javascript中实现多态,只需重写一个函数并给它一个和原方法形同的方法即可;

call和apply

arguments对象

公有,私有以及受保护的属性和方法

在构造函数中通过var定义的变量其作用域局限于该构造函数内——在prototype上定义的方法无法访问这个变量,因为这些方法有自己的作用域。要想通过公有的方法来访问私有的变量,需要创建一个同时包含两个作用域的新作用域,为此,我们可以创建一个自我执行的函数,称为闭包。该函数完全包含了类的定义,包括所有私有变量以及原型方法。

javascript有一个非强制性的但很有用的编程惯例,就是对所有私有变量或函数名加一个下划线(_)作为前缀,以标识他们是私有的,这有助于你及项目组的其他成员更好的理解每个类的作者的意图。

// 我们将类定义包在一个自我执行的函数里,这个函数返回我们所创建的类并将其保存在一个变量中,一边在后面的代码中使用
var Accommodation = (function(){
//定义类的构造函数,因为处于一个新的函数内,我们也切换到了一个新的作用域中,所以可以使用与保存函数返回值得那个变量相同的名字
function Accommodation(){
//此处定义的变量都是私有的,这些变量在当前作用域之外不可用,可以通过变量名添加下划线前缀来标识这一点
var _isLocked = false,
_isAlarmed = false,
_alarmMessage = "Alarm activated!";
//仅在当前作用域中定义的函数(未在构造函数上定义的)也是私有的
function _alarm(){
_isAlarmed = true;
alert(_alarmMessage);
} function _disableAlarm(){
_isAlarmed = false;
} //所有定义在原型上的方法都是公有的,当我们在此处创建爱你的类在闭包结束处被返回后,就可以在当前作用域之外访问这些方法了
Accommodation.prototype.lock =function(){
_isLocked = true;
_alarm();
} Accommodation.prototype.unlock = function(){
_isLocked = false;
_disableAlarm();
} //定义一个getter函数来对私有变量_islocked的值进行只读访问——相当于把该变量定义为了受保护的
Accommodation.prototype.getIsLocked = function(){
return _isLocked;
} //定义一个setter函数来对私有变量_alarmMessage进行只写访问——相当于将其定义为了受保护的
Accommodation.prototype.setAlarmMessage = function(message){
_alarmMessage = message;
} //返回在这个作用域中创建的类,使之在外层作用域中即后面的代码中的所有位置都可用,只有公有的属性和方法是可用的
return Accommodation;
}
}());

面向对象的JavaScript-小结的更多相关文章

  1. 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型

    前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...

  2. 前端开发:面向对象与javascript中的面向对象实现(一)

    前端开发:面向对象与javascript中的面向对象实现(一) 前言: 人生在世,这找不到对象是万万不行的.咱们生活中,找不到对象要挨骂,代码里也一样.朋友问我说:“嘿,在干嘛呢......”,我:“ ...

  3. 面向对象的 JavaScript

    面向对象的javascript 一.创建对象 创建对象的几种方式: var obj = {}; var obj = new Object(); var obj = Object.create(fath ...

  4. 摘抄--全面理解面向对象的 JavaScript

    全面理解面向对象的 JavaScript JavaScript 函数式脚本语言特性以及其看似随意的编写风格,导致长期以来人们对这一门语言的误解,即认为 JavaScript 不是一门面向对象的语言,或 ...

  5. 面向对象的JavaScript --- 动态类型语言

    面向对象的JavaScript --- 动态类型语言 动态类型语言与面向接口编程 JavaScript 没有提供传统面向对象语言中的类式继承,而是通过原型委托的方式来实现对象与对象之间的继承. Jav ...

  6. 面向对象的JavaScript --- 封装

    面向对象的JavaScript --- 封装 封装 封装的目的是将信息隐藏.一般而言,我们讨论的封装是封装数据和封装实现.真正的封装为更广义的封装,不仅包括封装数据和封装实现,还包括封装类型和封装变化 ...

  7. 面向对象的JavaScript --- 多态

    面向对象的JavaScript --- 多态 多态 "多态"一词源于希腊文 polymorphism,拆开来看是poly(复数)+ morph(形态)+ism,从字面上我们可以理解 ...

  8. 面向对象的JavaScript --- 原型模式和基于原型继承的JavaScript对象系统

    面向对象的JavaScript --- 原型模式和基于原型继承的JavaScript对象系统 原型模式和基于原型继承的JavaScript对象系统 在 Brendan Eich 为 JavaScrip ...

  9. 第1章 面向对象的JavaScript

    针对基础知识的每一个小点,我都写了一些小例子,https://github.com/huyanluanyu1989/DesignPatterns.git,便于大家理解,如有疑问,大家可留言给我,最近工 ...

  10. javascript面向对象之Javascript 继承

    转自原文javascript面向对象之Javascript 继承 在JavaScript中实现继承可以有多种方法,下面说两种常见的. 一,call 继承 先定义一个“人”类 //人类 Person=f ...

随机推荐

  1. round函数解决oracle报错"OCI-22053: 溢出错误"的问题

    继上次公司网站报错除数为0的问题,这次又来报错溢出错误,还是同一条语句!搜索网上的解决方法,发现问题描述和解决方法如下: Oracle 数值数据类型最多可存储 38 个字节的精度.当将 Oracle ...

  2. 网络通信协议,TCP和UDP 的区别

    1.网络通信   互联网本质就是一系列的网络通信,互联网协议的功能是定义计算机如何介入internet,以及介入internet的计算机通信的标准.互联网协议按照功能不同分为osi7层或tcp/ip五 ...

  3. Ubuntu18.04下给PyCharm创建快捷方式

    Ubuntu18.04下给PyCharm创建快捷方式 该方法 WebStorm.PyCharm.Clion 等都适用. 步骤 终端输入: sudo gedit /usr/share/applicati ...

  4. Qt UI tips

    窗口居中:  adjustSize(); move((availableGeometry.width() - width()) / 2, (availableGeometry.height() - h ...

  5. Python爬虫入门之Urllib库的高级用法

    1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Headers 的属性. 首先,打开我们的浏览 ...

  6. presto 判断数据量是否大于一个比较小的值的优化

    问题来源于以下场景: 我们需要对一张数据表做导出文件操作,需要判断如果数据量不多的时候,直接导出提供下载,如果数据量超过一定数值,则异步处理导出和下载. 这里就引入一个问题,如果我们直接count一张 ...

  7. 举例跟踪linux内核系统调用

    学号351+ 原创作品转载请注明出处 + 中科大孟宁老师的linux操作系统分析: https://github.com/mengning/linuxkernel/ 实验要求: 编译内核5.0 qem ...

  8. 接口自动化测试遭遇问题,excel中取出来的json串,无法使用requests去请求解决办法

    最近遭遇了一个问题,问题不大不小,想半天没想明白是哪里有问题,今天终于解决了 用python读取了excel用例中,body json字符串内容,然后requests去请求内容,结果一直报错,一直不明 ...

  9. 《JavaScript Dom 编程艺术》读书笔记-第10章

    用JS实现动画~内容包括: 1. 动画基础知识 2. 用动画丰富网页的浏览效果 动画就是让元素的位置随时间而不断变化. 位置: //CSSelement{ position:absolute; top ...

  10. [AutoMapper]反射自动注册AutoMapper Profile

    AutoMapper 帮我我们方便管理物件跟物件之间属性值格式转换 模型转换 这里有两个类别 UserInfoModel 当作我们从DB捞取出来模型资料 public class UserInfoMo ...