简单理解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 相关文章推荐
用roll.js实现的图片自动滚动+鼠标触动的特效
Mar 18 Javascript
prototype Element学习笔记(篇二)
Oct 26 Javascript
学习JavaScript的最佳方法分享
Oct 21 Javascript
js replace 与replaceall实例用法详解
Aug 03 Javascript
jQuery的load()方法及其回调函数用法实例
Mar 25 Javascript
javascript实现抽奖程序的简单实例
Jun 07 Javascript
jQuery在header中设置请求信息的方法
Mar 06 Javascript
详解vue axios二次封装
Jul 22 Javascript
详解Vue前端生产环境发布配置实战篇
May 07 Javascript
微信小程序开发实现的选项卡(窗口顶部/底部TabBar)页面切换功能图文详解
May 14 Javascript
Vue实现验证码功能
Dec 03 Javascript
vue 页面回退mounted函数不执行的解决方案
Jul 26 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
php Smarty模板生成html文档的方法
2010/04/12 PHP
使用JSON实现数据的跨域传输的php代码
2011/12/20 PHP
PHP+Redis链表解决高并发下商品超卖问题(实现原理及步骤)
2020/08/03 PHP
javascript document.execCommand() 常用解析
2009/12/14 Javascript
JavaScript 常用函数
2009/12/30 Javascript
屏蔽Flash右键信息的js代码
2010/01/17 Javascript
JavaScript高级程序设计 读书笔记之九 本地对象Array
2012/02/27 Javascript
Node.js实战 建立简单的Web服务器
2012/03/08 Javascript
JavaScript中的Function函数
2015/08/27 Javascript
原生js实现自由拖拽弹窗代码demo
2016/06/29 Javascript
8 行 Node.js 代码实现代理服务器
2016/12/05 Javascript
详谈js对url进行编码和解码(三种方式的区别)
2017/08/16 Javascript
vue中echarts3.0自适应的方法
2018/02/26 Javascript
layui 选择列表,打勾,点击确定返回数据的例子
2019/09/02 Javascript
详解小程序如何动态绑定点击的执行方法
2019/11/26 Javascript
vue调用微信JSDK 扫一扫,相册等需要注意的事项
2021/01/03 Vue.js
通过Python使用saltstack生成服务器资产清单
2016/03/01 Python
python之Socket网络编程详解
2016/09/29 Python
定制FileField中的上传文件名称实例
2017/08/23 Python
python实现人机猜拳小游戏
2020/02/03 Python
Pandas —— resample()重采样和asfreq()频度转换方式
2020/02/26 Python
Python timeit模块原理及使用方法
2020/10/10 Python
python的scipy.stats模块中正态分布常用函数总结
2021/02/19 Python
Python3爬虫RedisDump的安装步骤
2021/02/20 Python
CSS3截取字符串实例代码【推荐】
2018/06/07 HTML / CSS
美国成衣女装品牌:CHICO’S
2016/09/19 全球购物
专升本自我鉴定
2013/10/10 职场文书
工程资料员岗位职责
2014/03/10 职场文书
应届大学生自荐书
2014/06/17 职场文书
房屋授权委托书范本
2014/10/07 职场文书
比赛主持人开场白
2015/05/29 职场文书
2016年小学生寒假总结
2015/10/10 职场文书
党性教育心得体会(共6篇)
2016/01/21 职场文书
vue使用localStorage持久性存储实现评论列表
2022/04/14 Vue.js
vue动态绑定style样式
2022/04/20 Vue.js
box-shadow单边阴影的实现
2023/05/21 HTML / CSS