简单理解JavaScript中的封装与继承特性


Posted in Javascript onMarch 19, 2016

JavaScript中的封装
封装简单地说就是让外界只能访问对象的共有变量和函数,隐藏细节和数据。
js中有三种方法创建对象,分别为门户大开型、用命名规范区分私有变量、闭包创建真正的私有变量三种。
1.门户大开型,是实现对象的最基础的方法,所有方法与变量都是共有的外界可以访问。

var Book = function(name){ 
  if(this.check(name)){ 
    console.log("error"); 
    throw new Error("name null"); 
  } 
  this.name = name; 
} 
Book.prototype = { 
  check:function(name){ 
    if(!name){ 
      return true; 
    } 
  }, 
  getName:function(){ 
    return this.name; 
  } 
} 
 
var book = new Book("哈哈"); 
//output:哈哈 哈哈 
console.log(book.name,book.getName());

这个例子是门户大开型的典型,外界能直接访问对象的属性和方法。可以注意到属性和变量都有"this"来创建。
 
2.用命名规范区分私有变量,该方法是门户大开型的优化版本,只不过是在私有变量或方法前面用"_"区分,如果有程序员有意使用_getName()的方法来调用方法,还是无法阻止的,不是真正地将变量隐藏。
 
3.闭包创建真正的私有变量,该方法利用js中只有函数具有作用域的特性,在构造函数的作用域中定义相关变量,这些变量可以被定义域该作用域中的所有函数访问。

var Book2 = function(name){ 
  if(check(name)){ 
    console.log("error"); 
    throw new Error("name null"); 
  } 
  name = name; 
  function check(name){ 
    if(!name){ 
      return true; 
    } 
  } 
  this.getName = function(){ 
    return name; 
  } 
} 
Book2.prototype = { 
  display:function(){ 
    //无法直接访问name 
    return "display:"+this.getName(); 
  } 
} 
var book2 = new Book2("哈哈"); 
//output:undefined "哈哈" "display:哈哈" 
console.log(book2.name,book2.getName(),book2.display());

 可以看到,这个例子中的结果,直接访问name会返回undefined的结果。可以看到这个例子与门户大开型的区别,门户大开型中的变量使用"this"来创建,而这个例子中使用var来创建,check函数也是如此,使得name与check函数只能在构造函数的作用域中访问,外界无法直接访问。
该方法解决了前两种方法的问题,但是也有一定的弊端。在门户大开型对象创建模式中,所有方法都创建在原型对象中,因此不管生成多少对象实例,这些方法在内存中只存在一份,而采用该方法,每生成一个新的对象都会为每个私有变量和方法创建一个新的副本,故会耗费更多的内存。

JavaScript中的继承
Book基类:

var Book = function(name){ 
  if(this.check(name)){ 
    console.log("error"); 
    throw new Error("name null"); 
  } 
  this.name = name; 
} 
Book.prototype = { 
  check:function(name){ 
    if(!name){ 
      return true; 
    } 
  }, 
  getName:function(){ 
    return this.name; 
  } 
}

继承方法:

function extend(subClz,superClz){ 
var F = function(){} 
F.prototype = superClz.prototype; 
subClz.prototype = new F(); 
subClz.prototype.constructor = subClz; 
subClz.superClass = superClz.prototype; 
if(superClz.prototype.constructor == Object.prototype.constructor){ 
  superClz.prototype.constructor = superClz; 
}

 
使用空函数F作为桥接,可以避免直接实例化父类时调用父类的构造函数带来额外开销,而且当父类的构造函数有参数时,想直接通过subClass.prototype = new superClass();实现父类构造函数的调用和原型链的继承是不行的。

subClz.superClass = superClz.prototype; 
if(superClz.prototype.constructor == Object.prototype.constructor){ 
  superClz.prototype.constructor = superClz; 
}

 
添加这三句可以避免子类继承父类写Book.call(this,name);而是简单地写ArtBook.superClass.Constructor.call(this,name)便能实现。
并且在子类重写父类方法的时候,可以调用到父类的方法:

ArtBook.prototype.getName = functiion(){ 
  return ArtBook.superClass.getName.call(this) + "!!!"; 
}

ArtBook子类:

var ArtBook = function(name,price){ 
  ArtBook.superClass.Constructor.call(this,name); 
  this.price = price; 
} 
extend(ArtBook,Book); 
ArtBook.prototype.getPrice = function(){ 
    return this.price; 
} 
ArtBook.prototype.getName = function(){ 
   return ArtBook.superClass.getName.call(this)+"!!!"; 
 }
Javascript 相关文章推荐
Jquery chosen动态设置值实例介绍
Aug 08 Javascript
js 距离某一时间点时间是多少实现代码
Oct 14 Javascript
简单的js图片轮换代码(js图片轮播)
May 06 Javascript
jquery图片切换实例分析
Apr 15 Javascript
每天一篇javascript学习小结(Boolean对象)
Nov 12 Javascript
JQuery实现网页右侧随动广告特效
Jan 17 Javascript
AngularJS中监视Scope变量以及外部调用Scope方法
Jan 23 Javascript
KnockoutJS 3.X API 第四章之click绑定
Oct 10 Javascript
深入了解query和params的使用区别
Jun 24 Javascript
你不可不知的Vue.js列表渲染详解
Oct 01 Javascript
Vue3 中的数据侦测的实现
Oct 09 Javascript
JavaScript前端面试组合函数
Jun 21 Javascript
JavaScript的函数式编程基础指南
Mar 19 #Javascript
深入解析JavaScript中函数的Currying柯里化
Mar 19 #Javascript
Linux下为Node.js程序配置MySQL或Oracle数据库的方法
Mar 19 #Javascript
分享js粘帖屏幕截图到web页面插件screenshot-paste
Aug 21 #Javascript
JQuery用户名校验的具体实现
Mar 18 #Javascript
基于javascript实现页面加载loading效果
Sep 15 #Javascript
JQuery fileupload插件实现文件上传功能
Mar 18 #Javascript
You might like
解决中英文字符串长度问题函数
2007/01/16 PHP
PHP SPL标准库之SplFixedArray使用实例
2015/05/12 PHP
PHP基于cookie与session统计网站访问量并输出显示的方法
2016/01/15 PHP
利用laravel搭建一个迷你博客实战教程
2017/08/13 PHP
thinkphp中的多表关联查询的实例详解
2017/10/12 PHP
在模板页面的js使用办法
2010/04/01 Javascript
javascript面向对象入门基础详细介绍
2012/09/05 Javascript
JS 获取浏览器和屏幕宽高等信息的实现思路及代码
2013/07/31 Javascript
angular中使用路由和$location切换视图
2015/01/23 Javascript
js游戏人物上下左右跑步效果代码分享
2015/08/28 Javascript
使用JavaScript为Kindeditor自定义按钮增加Audio标签
2016/03/18 Javascript
KnockoutJS 3.X API 第四章之数据控制流with绑定
2016/10/10 Javascript
AngularJS中directive指令使用之事件绑定与指令交互用法示例
2016/11/22 Javascript
js自定义QQ菜单效果
2017/01/10 Javascript
借助node实战JSONP跨域实例
2017/03/30 Javascript
为你的微信小程序体积瘦身详解
2017/05/20 Javascript
Mobile Web开发基础之四--处理手机设备的横竖屏问题
2017/08/11 Javascript
无限循环轮播图之运动框架(原生JS实现)
2017/10/01 Javascript
vue-cli+webpack项目 修改项目名称的方法
2018/02/28 Javascript
vue的常用组件操作方法应用分析
2018/04/13 Javascript
Vue单页及多页应用全局配置404页面实践记录
2018/05/22 Javascript
详解extract-text-webpack-plugin 的使用及安装
2018/06/12 Javascript
vue 右键菜单插件 简单、可扩展、样式自定义的右键菜单
2018/11/29 Javascript
JS对象和字符串之间互换操作实例分析
2019/02/02 Javascript
使用koa2创建web项目的方法步骤
2019/03/12 Javascript
VUE 组件转换为微信小程序组件的方法
2019/11/06 Javascript
python实现简单温度转换的方法
2015/03/13 Python
开启Django博客的RSS功能的实现方法
2020/02/17 Python
pycharm设置python文件模板信息过程图解
2020/03/10 Python
医校毕业生自我鉴定
2014/01/25 职场文书
《美丽的彩虹》教学反思
2014/02/25 职场文书
幼儿园小班评语
2014/04/18 职场文书
五分钟演讲稿
2014/04/30 职场文书
关于教师节的广播稿
2014/09/10 职场文书
法律进社区活动总结
2015/05/07 职场文书
MySQL 亿级数据导入导出及迁移笔记
2021/06/18 MySQL