简单理解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 判断checkbox是否选中的操作方法
Nov 09 Javascript
Jquery时间验证和转换工具小例子
Jul 01 Javascript
javascript实现多栏闭合展开式广告位菜单效果实例
Aug 05 Javascript
jQuery实现的指纹扫描效果实例(附演示与demo源码下载)
Jan 26 Javascript
纯JS焦点图特效实例(可一个页面多用)
Dec 07 Javascript
详解JavaScript中js对象与JSON格式字符串的相互转换
Feb 14 Javascript
vue loadmore组件上拉加载更多功能示例代码
Jul 19 Javascript
Vue中的slot使用插槽分发内容的方法
Mar 01 Javascript
基于Vue 实现一个中规中矩loading组件
Apr 03 Javascript
vue通过数据过滤实现表格合并
Nov 30 Javascript
原生js中运算符及流程控制示例详解
Jan 05 Javascript
jQuery实现广告显示和隐藏动画
Jul 04 jQuery
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
人脸识别测颜值、测脸龄、测相似度微信接口
2016/04/07 PHP
Jquery获取复选框被选中值的简单方法
2013/07/04 Javascript
JS中typeof与instanceof之间的区别总结
2013/11/14 Javascript
struts2+jquery组合验证注册用户是否存在
2014/04/30 Javascript
jQuery使用siblings获取某元素所有同辈(兄弟姐妹)元素用法示例
2017/01/30 Javascript
详解vue-admin和后端(flask)分离结合的例子
2018/02/12 Javascript
Vue中的字符串模板的使用
2018/05/17 Javascript
Vue.js实现的计算器功能完整示例
2018/07/11 Javascript
vuex + axios 做登录验证 并且保存登录状态的实例
2018/09/16 Javascript
使用JavaScript保存文本文件到本地的两种方法
2019/01/22 Javascript
layui实现左侧菜单点击右侧内容区显示
2019/07/26 Javascript
JS 数组基本用法入门示例解析
2020/01/16 Javascript
阿望教你用vue写扫雷小游戏
2020/01/20 Javascript
Vue.js获取手机系统型号、版本、浏览器类型的示例代码
2020/05/10 Javascript
vue项目打包后提交到git上为什么没有dist这个文件的解决方法
2020/09/16 Javascript
[02:41]2015国际邀请赛中国区预选赛观战指南
2015/05/20 DOTA
浅谈Python 集合(set)类型的操作——并交差
2016/06/30 Python
详解Python计算机视觉 图像扭曲(仿射扭曲)
2019/03/27 Python
python使用MQTT给硬件传输图片的实现方法
2019/05/05 Python
Python内置类型性能分析过程实例
2020/01/29 Python
python GUI库图形界面开发之PyQt5中QMainWindow, QWidget以及QDialog的区别和选择
2020/02/26 Python
Pycharm安装并配置jupyter notebook的实现
2020/05/18 Python
Pytorch框架实现mnist手写库识别(与tensorflow对比)
2020/07/20 Python
CSS3教程(6):创建网站多列
2009/04/02 HTML / CSS
HTML5 本地存储和内容按需加载的思路和方法
2011/04/07 HTML / CSS
美国大城市最热门旅游景点门票:CityPASS
2016/12/16 全球购物
俄罗斯美容和健康网上商店:Созвездие Красоты
2019/07/23 全球购物
电气工程及其自动化学生实习自我鉴定
2013/09/19 职场文书
大二自我鉴定范文
2013/10/05 职场文书
公关活动策划方案
2014/05/25 职场文书
群众路线党员自我评议范文2014
2014/09/24 职场文书
银行委托书范本
2014/09/28 职场文书
小学教师自我剖析材料
2014/09/29 职场文书
驳回起诉民事裁定书
2015/05/19 职场文书
卢旺达饭店观后感
2015/06/05 职场文书
python通过函数名调用函数的几种方法总结
2021/06/07 Python