我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧!

我们都知道JavaScript是面向对象的语言,但是JavaScript是弱类型语言,没有比如C#这些强类型语言那种通过class等关键字实现类的封装方式,不过我们可以通过一些特性模仿实现类型的功能。

首先我们创建一个类

var Students=function(id,name,age){
this.id=id;
this.name=name;
this.age=age;
}

当然也可以像我们之前讲的那样通过在类的原型上添加属性和方法,比如

Students.prototype={
getStuInfo:function(){ }
};

当然这两种方法不要混合使用

这样我们就把我们需要的属性和方法都封装在我们抽象的Student类里了,当我们使用功能方法的时候我们不能直接使用这个类,需要用new关键字来实例化创建新的对象。

var student=new Students(1,'张三',20);

这样我们通过student.name的方式得到张三这个人的姓名。

或许有人会问了你通过this也可以添加属性和方法通过prototype也能添加属性和方法,那么这两者有什么区别呢?

是这样的JavaScript是一种基于原型prototype的语言所以每创建一个对象时,它都有一个原型prototype用于指向其继承的属性、方法。

那么通过prototype继承的方法并不是对象自身的所以我们每次通过类创建一个新对象时原来的这些属性和方法不会再次创建。

而通过this添加的属性、方法是在当前对象上添加的,每次创建新对象this所指向的属性和方法都会得到相应的创建。

既然我们已经能创建类,那么类里面对属性方法的隐藏和暴露我们也能通过JavaScript的函数级作用域来模仿实现

var Students=function(id,name,age)
{
//私有属性
var hobby='学习';
//私有方法
function learningMethod(){ };
//特权方法
this.getName=function(){};
this.setName=function(){};
this.getAge=function(){};
this.setAge=function(){};
//对象公有属性
this.id=id;
//对象公有方法
this.replication=function(){};
//构造器
this.setName(name);
this.setAge(age);
};

正如我上面示例中一样,声明在函数内部的变量外界是访问不到的通过这个特性我们可以创建类的私有变量以及私有方法。

而通过this创建的属性和方法,在类创建时都会相应创建,因此我们可以看成是公有属性和公有方法。

还有部分通过this创建的方法,可以访问到类或对象自身的私有属性和私有方法,我们可以看做特权方法,特权方法也可以看做是类的构造器。

那么我们在类的外部通过点语法定义的属性和方法以及在外部通过prototype定义的属性和方法又有什么作用呢?

直接通过点语法定义的属性和方法,我们在新创建的对象中无法获取他们,但是可以通过类来使用,所以我们称他们为类的静态公有属性和类的静态公有方法。

而prototye添加的属性和方法,我们在类的实例对象中可以通过this访问所以我们依然称他们为类的公有属性,和类的公有方法。

Students.primary=true;//类的静态公有属性
Students.admissionTime=function(){
console.log("2017");
};//类的静态公有方法
Students.prototype={
//公有属性
middle:false,
//公有方法
resetTime:function(){}
}

通过new关键字创建的对象的实质是对新对象this的不断赋值,并将prototype所指向类的prototype所指向的对象,听上去比较绕口,因为prototype是一级一级来查找得到的所以我们只要理解为最后会找到这个对象原型的根就行了。

所以在类的构造函数外面通过点语法定义的属性和方法是不会添加到新创建的对象上去的而通过类的原型prototype定义的对象就可以直接在新对象里使用,因为新对象的prototype和类的prototype指向的是同一个对象

我们可以测试一下,我们先实例化我们之前的Students类,然后用log打印出来看看具体显示什么

var student=new Students(1,'张三',23);
console.log(student.hobby);//undefined
console.log(student.middle);//false
console.log(student.id);//1
console.log(student.primary);//undefined

我们可以看到类的私有属性和类的静态公有属性在新创建的student对象里是访问不到的,而类的公有属性在student对象中可以通过点语法访问的到。

如同我们之前提到的类的静态公有属性和方法可以通过类的自身访问。

console.log(Students.primary);//true
Students.admissionTime();//2017

一般我们将类的静态变量通过闭包来实现

var Students=(function(){
//静态私有变量
var hobby='学习';
var studentNum=0;
//静态私有方法
function learningMethod(name){ };
//创建类
function student(newId,newName,newAge){
//私有变量
var name,age;
//私有方法
function checkId(id){};
//特权方法
this.getName=function(){};
this.setName=function(){};
this.getAge=function(){};
this.setAge=function(){};
//公有属性
this.id=newId;
//公有方法
this.replication=function(){};
if(studentNum>10)
throw new Error('我们只招收10名学生。');
//构造器
this.setName(name);
this.setAge(age);
}
//构造原型
student.prototype={
//静态公有属性
middle:false,
//静态公有方法
resetTime:function(){}
};
return student;
})();

这里我们介绍一下闭包,闭包是指有权限访问另一个函数作用域中变量的函数,即在一个函数内部创建另一个函数。

我们将这个闭包作为创建对象的构造函数,这样它既是闭包又是可实例的对象函数。

但是这样写好像还是有点美中不足,在JavaScript中并没有像C#那样的智能提示,在创建对象的时候没有使用new关键字不会给出错误提示,现在我们看如果我们创建对象不给new会怎么样。

现在我们用最开始的那个例子做示例

var Students=function(id,name,age){
this.id=id;
this.name=name;
this.age=age;
}
var student=Students(1,'张三',17);

你看我们实例化了一个叫张三的学生现在我们用log打印出来看看

console.log(student);//undefined

实际上他会显示未定义,为什么会出现这种情况呢?

我们再来打印3个属性看看

console.log(window.id);//1
console.log(window.name);//张三
console.log(window.age);//17

我们会发现我们创建了一个Students对象,但是赋值的属性添加到了window上面与,这是因为我们没用new关键字来实例化,new关键字可以看作是对当前对象的this不停的赋值。

所以,这个函数在全局中执行了,而全局作用域的this指向的当前对象就是全局变量,所以添加到Studnets的属性被添加到了window上面。

那我们如何去避免这个问题呢?

我们可以用instanceof去判断实例的是否是当前的对象如果不是,我们重新创建这个对象

var Students=function(id,name,age){
if(this instanceof Students){
this.id=id;
this.name=name;
this.age=age;
}else{
return new Students(id,name,age);
}
}
var student=Students(1,'张三',17);

我们再来看一看打印出来的东西吧

console.log(student);//Students

现在我们就能直接把对象打印出来了。

好了以上就是本次分享的全部内容,本次示例参考自JavaScript设计模式一书,让我们一点点积累一点点成长,希望对大家有所帮助。

再起航,我的学习笔记之JavaScript设计模式02的更多相关文章

  1. 再起航,我的学习笔记之JavaScript设计模式01

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 在通 ...

  2. 再起航,我的学习笔记之JavaScript设计模式03

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 上一 ...

  3. 再起航,我的学习笔记之JavaScript设计模式04

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 上回 ...

  4. 再起航,我的学习笔记之JavaScript设计模式05(简单工程模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...

  5. 再起航,我的学习笔记之JavaScript设计模式06(工厂方法模式)

    上一次已经给大家介绍了简单工厂模式,相信大家对创建型设计模式有了初步的了解,本次我将给大家介绍的是工厂方法模式. 工厂方法模式 工厂方法模式(Factory Method):通过对产品类的抽象使其创建 ...

  6. 再起航,我的学习笔记之JavaScript设计模式05(简单工厂模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...

  7. 再起航,我的学习笔记之JavaScript设计模式06(抽象工厂模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前两 ...

  8. 再起航,我的学习笔记之JavaScript设计模式08(建造者模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...

  9. 再起航,我的学习笔记之JavaScript设计模式09(原型模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 我们 ...

随机推荐

  1. JavaScript面向对象之Windows对象

    JavaScript之Window对象 首先我们先了解一个概念:事件. 事件,就是把一段代码设置好,满足条件时触发.或者说,事件是可以被 JavaScript 侦测到的行为. 网页中每个元素都可以触发 ...

  2. Python 基础 (单、双引号区别) 不断补充

    最近开始学习Python ,一些小细节的东西不是很理解,所以就记录一下,方便自己以后查看. 我的Python环境: Mac pro 10.12.3,Python3.5 ,Pycharm 多句题外话:公 ...

  3. 浅谈Swift和OC的区别

    前言 转眼Swift3都出来快一年了,从OC到Swift也经历了很多,所以对两者的一些使用区别也总结了一点,暂且记录下,权当自己的一个笔记. 当然其中一些区别可能大家都有耳闻,所以这里也会结合自身的一 ...

  4. Spring+SpringMVC+MyBatis深入学习及搭建(十四)——SpringMVC和MyBatis整合

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7010363.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十三)--S ...

  5. 使用Ansible进行项目的自动部署(Tomcat、Weblogic)

    原文:https://github.com/x113773/testall/issues/4 问题:Weblogic/Tomcat 通过JAVA直接远程调用或者调用本地Shell还是通过Ansible ...

  6. Redis事务原理分析

    Redis事务原理分析 基本应用 在Redis的事务里面,采用的是乐观锁,主要是为了提高性能,减少客户端的等待.由几个命令构成:WATCH, UNWATCH, MULTI, EXEC, DISCARD ...

  7. tomcat 修改为自己项目界面

    修改Tomcat欢迎界面为自己项目界面 Posted on 2011-04-16 13:10 IceWee 阅读(1062) 评论(0)  编辑  收藏 所属分类: Tomcat  由于项目要发布到互 ...

  8. 仿网易新闻app下拉标签选择菜单

    仿网易新闻app下拉标签选择菜单 仿网易新闻app下拉标签选择菜单,长按拖动排序,点击增删标签控件 ##示例  ##EasyTagDragView的使用 在layout布局里添加:  

  9. PeopleCode事件和方法只用于online界面不能用于组件接口(component interface)

    在使用CI过程中,哪些方法是不能使用的.以下为PeopleBook解释的内容. 一.搜索框代码不执行:SearchInit, SearchSave, and RowSelect events 意味着使 ...

  10. 对象序列化 输入输出流概念 InputOutStream OutputStream

    序列化:内存到文件   他是输出流        ObjectOutputStream  需要强制类型转换  必须实现seriazable接口 反序列化:文件到内存  输入流            O ...