简单理解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 相关文章推荐
js 深拷贝函数
Dec 04 Javascript
js定义对象或数组直接量时各浏览器对多余逗号的处理(json)
Mar 05 Javascript
分享28款免费实用的 JQuery 图片和内容滑块插件
Dec 15 Javascript
判断浏览器的内核及版本号方法汇总
Jan 05 Javascript
javascript制作sql转换为stringBuffer的小工具
Apr 03 Javascript
javascript表单处理具体实现代码(表单、链接、按钮)
May 07 Javascript
如何解决IONIC页面底部被遮住无法向上滚动问题
Sep 06 Javascript
微信小程序 生命周期和页面的生命周期详细介绍
Jan 19 Javascript
JQuery 又谈ajax局部刷新
Nov 27 jQuery
jQuery模拟html下拉多选框的原生实现方法示例
May 30 jQuery
在Angular中实现一个级联效果的下拉框的示例代码
May 20 Javascript
JavaScript 语句之常用 for 循环详解
Mar 29 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
DWZ+ThinkPHP开发时遇到的问题分析
2016/12/12 PHP
php 常用的系统函数
2017/02/07 PHP
php readfile下载大文件失败的解决方法
2017/05/22 PHP
PHP简单实现正则匹配省市区的方法
2018/04/13 PHP
php实现小程序支付完整版
2018/10/09 PHP
Laravel框架自定义验证过程实例分析
2019/02/01 PHP
php探针不显示内存解决方法
2019/09/17 PHP
找到一点可怜的关于dojo资料,谢谢作者!
2006/12/06 Javascript
JQuery 确定css方框模型(盒模型Box Model)
2010/01/22 Javascript
JavaScript Perfection kill 测试及答案
2010/03/23 Javascript
JS的事件绑定深入认识
2014/06/26 Javascript
使用javascript实现监控视频播放并打印日志
2015/01/05 Javascript
原生Js实现简易烟花爆炸效果的方法
2015/03/20 Javascript
javascript 判断页面访问方式电脑或者移动端
2016/09/19 Javascript
jquery popupDialog 使用 加载jsp页面的方法
2016/10/25 Javascript
Vue关于数据绑定出错解决办法
2017/05/15 Javascript
js每隔两秒输出数组中的一项(实例)
2017/05/28 Javascript
[js高手之路]图解javascript的原型(prototype)对象,原型链实例
2017/08/28 Javascript
JS计算距当前时间的时间差实例
2017/12/29 Javascript
vue2.0 根据状态值进行样式的改变展示方法
2018/03/13 Javascript
vue 项目打包通过命令修改 vue-router 模式 修改 API 接口前缀
2018/06/13 Javascript
vue中Element-ui 输入银行账号每四位加一个空格的实现代码
2018/09/14 Javascript
Easyui 关闭jquery-easui tab标签页前触发事件的解决方法
2019/04/28 jQuery
原生js基于canvas实现一个简单的前端截图工具代码实例
2019/09/10 Javascript
微信小程序国际化探索实现(附源码地址)
2020/05/20 Javascript
深入解析Python中函数的参数与作用域
2016/03/20 Python
Python实现自动打开电脑应用的示例代码
2020/04/17 Python
python opencv实现简易画图板
2020/08/27 Python
python import 上级目录的导入
2020/11/03 Python
CSS3+js实现简单的时钟特效
2015/03/18 HTML / CSS
Linux内核的同步机制是什么?主要有哪几种内核锁
2016/07/11 面试题
怎样有效的进行自我评价
2013/10/06 职场文书
工厂门卫岗位职责
2013/11/25 职场文书
关于幼儿的自我评价
2013/12/18 职场文书
护理专业求职信
2014/06/15 职场文书
小学语文教研活动总结
2014/07/01 职场文书