简单理解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 相关文章推荐
OfflineSave离线保存代码再次发布使用说明
May 23 Javascript
基于jquery编写的横向自适应幻灯片切换特效的实例代码
Aug 06 Javascript
使用js解决由border属性引起的div宽度问题
Nov 26 Javascript
Bootstrap CSS使用方法
Dec 23 Javascript
jQuery常见面试题之DOM操作详析
Jul 05 jQuery
angular动态删除ng-repaeat添加的dom节点的方法
Jul 20 Javascript
JavaScript生成简单等差数列
Nov 28 Javascript
详解Chai.js断言库API中文文档
Jan 31 Javascript
微信小程序组件传值图示过程详解
Jul 31 Javascript
Electron整合React使用搭建开发环境的步骤详解
Jun 07 Javascript
详解JavaScript 作用域
Jul 14 Javascript
Vue中强制组件重新渲染的正确方法
Jan 03 Vue.js
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数组函数序列之array_search()- 按元素值返回键名
2011/11/04 PHP
CodeIgniter错误mysql_connect(): No such file or directory解决方法
2014/09/06 PHP
PHPMailer ThinkPHP实现自动发送邮件功能
2018/06/10 PHP
js实现单一html页面两套css切换代码
2013/04/11 Javascript
多次注册事件会导致一个事件被触发多次的解决方法
2013/08/12 Javascript
基于MVC3方式实现下拉列表联动(JQuery)
2013/09/02 Javascript
在每个匹配元素的外部插入新元素的方法
2013/12/20 Javascript
使用jQuery获得内容以及内容的属性
2015/02/26 Javascript
理解javascript中Map代替循环
2016/02/26 Javascript
jquery显示隐藏元素的实现代码
2016/05/19 Javascript
jQuery leonaScroll 1.1 自定义滚动条插件(推荐)
2016/09/17 Javascript
Node.js dgram模块实现UDP通信示例代码
2017/09/26 Javascript
浅析vue深复制
2018/01/29 Javascript
微信小程序用户信息encryptedData详解
2018/08/24 Javascript
JS使用H5实现图片预览功能
2019/09/30 Javascript
[05:28]刀塔密之一:团结则存
2014/07/03 DOTA
python3 模拟登录v2ex实例讲解
2017/07/13 Python
Python实现的HMacMD5加密算法示例
2018/04/03 Python
Python基于百度AI的文字识别的示例
2018/04/21 Python
Python使用matplotlib和pandas实现的画图操作【经典示例】
2018/06/13 Python
python 划分数据集为训练集和测试集的方法
2018/12/11 Python
Scrapy框架爬取Boss直聘网Python职位信息的源码
2019/02/22 Python
Django使用Channels实现WebSocket的方法
2019/07/28 Python
Spring实战之使用util:命名空间简化配置操作示例
2019/12/09 Python
2020最新pycharm汉化安装(python工程狮亲测有效)
2020/04/26 Python
python Socket网络编程实现C/S模式和P2P
2020/06/22 Python
CSS3解决移动页面上点击链接触发色块的问题
2016/06/03 HTML / CSS
CSS3 实现发光边框特效
2020/11/11 HTML / CSS
学习新党章思想汇报
2014/01/09 职场文书
《月迹》教学反思
2014/02/19 职场文书
法人委托书
2014/07/31 职场文书
勿忘国耻9.18演讲稿(经典篇)
2014/09/14 职场文书
2015年医德考评自我评价
2015/03/03 职场文书
Java生成读取条形码和二维码的简单示例
2021/07/09 Java/Android
详解jQuery的核心函数和事件处理
2022/02/18 jQuery
前端canvas中物体边框和控制点的实现示例
2022/08/05 Javascript