简单理解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 相关文章推荐
鼠标移动到一张图片时变为另一张图片
Dec 05 Javascript
js浮动图片的动态效果
Jul 10 Javascript
jQuery读取和设定KindEditor值的方法
Nov 22 Javascript
jQuery中的$.ajax()方法应用
May 06 Javascript
JavaScript驾驭网页-获取网页元素
Mar 24 Javascript
Angular.js中下拉框实现渲染html的方法
Jun 18 Javascript
JavaScript中的FileReader图片预览上传功能实现代码
Jul 24 Javascript
Angular弹出模态框的两种方式
Oct 19 Javascript
[jQuery] 事件和动画详解
Mar 05 jQuery
解决layer.prompt无效的问题
Sep 24 Javascript
Nuxt.js nuxt-link与router-link的区别说明
Nov 06 Javascript
JavaScript实现点击自制菜单效果
Feb 02 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
虫族 ZERG 概述
2020/03/14 星际争霸
xml+php动态载入与分页
2006/10/09 PHP
一个php作的文本留言本的例子(五)
2006/10/09 PHP
php遍历删除整个目录及文件的方法
2015/03/13 PHP
PHP调用.NET的WebService 简单实例
2015/03/27 PHP
基于Laravel实现的用户动态模块开发
2017/09/21 PHP
深入学习微信网址链接解封的防封原理visit_type
2019/08/15 PHP
什么是JavaScript
2009/08/13 Javascript
浅析JavaScript中的常用算法与函数
2013/11/21 Javascript
使用POST方式弹出窗口的两种方法示例介绍
2014/01/29 Javascript
Jquery实现自定义tooltip示例代码
2014/02/12 Javascript
jquery选择器使用详解
2014/04/08 Javascript
js实现prototype扩展的方法(字符串,日期,数组扩展)
2016/01/14 Javascript
jQuery CSS3自定义美化Checkbox实现代码
2016/05/12 Javascript
JavaScript实现实时更新系统时间的实例代码
2017/04/04 Javascript
angularjs中ng-bind-html的用法总结
2017/05/23 Javascript
详解webpack进阶之插件篇
2017/07/06 Javascript
解决easyui日期时间框ie的兼容的问题
2018/03/01 Javascript
vue打包npm run build时候界面报错的解决
2020/08/13 Javascript
vue图片裁剪插件vue-cropper使用方法详解
2020/12/16 Vue.js
[48:21]林俊杰圣堂刺客超神杀戮秀
2014/10/29 DOTA
python妹子图简单爬虫实例
2015/07/07 Python
python中的随机函数小结
2018/01/27 Python
在Pycharm中执行scrapy命令的方法
2019/01/16 Python
利用python Selenium实现自动登陆京东签到领金币功能
2019/10/31 Python
使用pandas实现筛选出指定列值所对应的行
2020/12/13 Python
css3 图片圆形显示 如何CSS将正方形图片显示为圆形图片布局
2014/10/10 HTML / CSS
Subside Sports德国:足球球衣和球迷商品
2019/06/08 全球购物
设计部经理的岗位职责
2013/11/16 职场文书
计算机专业毕业生自荐信
2013/12/31 职场文书
商场主管竞聘书
2014/03/31 职场文书
父母寄语大全
2014/04/12 职场文书
开工典礼致辞
2015/07/29 职场文书
Python中常见的反爬机制及其破解方法总结
2021/06/10 Python
python scrapy简单模拟登录的代码分析
2021/07/21 Python
为了顺利买到演唱会的票用Python制作了自动抢票的脚本
2021/10/16 Python