简单理解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 插件 web2.0分格的分页脚本,可用于ajax无刷新分页
Dec 25 Javascript
ajax 文件上传应用简单实现
Mar 03 Javascript
Mootools 1.2教程 Tooltips
Sep 15 Javascript
基于jquery的一个拖拽到指定区域内的效果
Sep 21 Javascript
jQuery获取注册信息并提示实现代码
Apr 21 Javascript
本人自用的global.js库源码分享
Feb 28 Javascript
javascript实现PC网页里的拖拽效果
Mar 14 Javascript
基于javascript实现泡泡大冒险网页版小游戏
Mar 23 Javascript
JS实现简单抖动效果
Jun 01 Javascript
jQuery Ajax向服务端传递数组参数值的实例代码
Sep 03 jQuery
angularJs中orderBy筛选以及filter过滤数据的方法
Sep 30 Javascript
vue 验证码界面实现点击后标灰并设置div按钮不可点击状态
Oct 28 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
关于PHP5 Session生命周期介绍
2010/03/02 PHP
Drupal 添加模块出现莫名其妙的错误的解决方法(往往出现在模块较多时)
2011/04/18 PHP
php开发微信支付获取用户地址
2015/10/04 PHP
php开发工具有哪五款
2015/11/09 PHP
Yii框架参数化查询中IN查询只能查询一个的解决方法
2017/05/20 PHP
php curl获取到json对象并转成数组array的方法
2018/05/31 PHP
PHP实现的函数重载功能示例
2018/08/03 PHP
javascript 学习笔记(八)javascript对象
2011/04/12 Javascript
node.js中的fs.chownSync方法使用说明
2014/12/16 Javascript
JQuery实现动态适时改变字体颜色的方法
2015/03/10 Javascript
JavaScript获取服务器时间的方法详解
2016/12/11 Javascript
实现一个简单的vue无限加载指令方法
2017/01/10 Javascript
深入理解JavaScript继承的多种方式和优缺点
2017/05/12 Javascript
微信小程序中input标签详解及简单实例
2017/05/18 Javascript
Ionic + Angular.js实现图片轮播的方法示例
2017/05/21 Javascript
Vue官方文档梳理之全局配置
2017/11/22 Javascript
JS运动特效之同时运动实现方法分析
2018/01/24 Javascript
Es6 Generator函数详细解析
2018/02/24 Javascript
使用koa-log4管理nodeJs日志笔记的使用方法
2018/11/30 NodeJs
python游戏开发之视频转彩色字符动画
2019/04/26 Python
Python Socketserver实现FTP文件上传下载代码实例
2020/03/27 Python
python算的上脚本语言吗
2020/06/22 Python
css3图片边框border-image的用法
2017/06/30 HTML / CSS
CSS3支持IE6, 7, and 8的边框border属性
2012/12/28 HTML / CSS
英国、欧洲和全球租车服务:Avis英国
2016/08/29 全球购物
String和StringBuffer的区别
2015/08/13 面试题
中科软笔试题和面试题
2014/10/07 面试题
白酒市场营销方案
2014/02/25 职场文书
公司市场专员岗位职责
2014/06/29 职场文书
办公经费申请报告
2015/05/15 职场文书
同意落户证明
2015/06/19 职场文书
在酒桌上的敬酒词
2015/08/12 职场文书
入党转正申请书范文
2019/05/20 职场文书
python生成可执行exe控制Microsip自动填写号码并拨打功能
2021/06/21 Python
2021年国产动漫公司排行前十名,玄机科技上榜,第二推出过铠甲勇士
2022/03/18 杂记
mysql查看表结构的三种方法总结
2022/07/07 MySQL