我的学习笔记是根据我的学习情况来定期更新的,预计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函数之递归

    递归 递归的本质就是使用函数自身来解决问题的思路. 递归的定义(摘): 程序调用自身的编程技巧称为递归( recursion).递归做为一种算法在程序设计语言中广泛应用. 一个过程或函数在其定义或说明 ...

  2. python 标准库 -- glob

    glob glob.glob() import glob l = glob.glob("/root/*") # 返回列表 print l # 输出如下 ['/root/databa ...

  3. 选课 树形DP+多叉树转二叉树+dfs求解答案

    问题 A: 选课 时间限制: 1 Sec  内存限制: 128 MB 题目描述 大 学里实行学分.每门课程都有一定的学分,学生只要选修了这门课并考核通过就能获得相应的学分.学生最后的学分是他选修的各门 ...

  4. 如何在BCGControlBar界面库的CBCGPFormView子视图里面添加工具栏

    最近有一个项目需求,需要在子视图里面添加一个新工具栏用来处理当前视图对应模块的操作.之前在对话框模式下做过添加工具栏的实现,在CBCGPFormView中添加工具栏还是头一次.在这里记录一下,给自己留 ...

  5. 手把手教你从基础学习JQuery

    JQuery JQuery 语法 1.jQuery("选择器").action();通过选择器调用事件函数 但jQuery中,jQuery可以用$代替,即$("选择器&q ...

  6. Oracle数据库web维护客户端管理工具软件

    TreeSoft数据库管理系统使用JAVA开发,采用稳定通用的springMVC +JDBC架构,实现基于WEB方式对 MySQL,Oracle,PostgreSQL 等数据库进行维护管理操作. 功能 ...

  7. python list有关remove的问题

    在python 中进行一次简单的列表循环,当用到remove时出现了一个很有趣的现象, 代码如下: a=range(30) for i in a : if i%4!=0: a.remove(i) 这段 ...

  8. ASP.NET Core配置Kestrel 网址Urls

    ASP.NET Core中如何配置Kestrel Urls呢,大家可能都知道使用UseUrls() 方法来配置. 今天给介绍全面的ASP.NET Core 配置 Urls,使用多种方式配置Urls.让 ...

  9. CSS3学习系列之布局样式(一)

    多栏布局 使用float属性或position属性的缺点: 使用float属性或position属性进行页面中的简单布局的例子. <!DOCTYPE html> <html lang ...

  10. Python查看MQ队列深度

    分享一段代码,很简单但是也很实用. #!/usr/bin/python #-*- coding:gb18030 -*- ''' Usage: mq.py [Qmgr] *get the queues' ...