简单理解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 .tmpl(), .template()学习资料小结
Jul 18 Javascript
JS控制弹出新页面窗口位置和大小的方法
Mar 02 Javascript
Markdown+Bootstrap图片自适应属性详解
May 21 Javascript
JS留言功能的简单实现案例(推荐)
Jun 23 Javascript
gulp-uglify 与gulp.watch()配合使用时报错(重复压缩问题)
Aug 24 Javascript
vue多种弹框的弹出形式的示例代码
Sep 18 Javascript
JavaScript 异步调用
Oct 25 Javascript
如何手动实现es5中的bind方法详解
Dec 07 Javascript
JavaScript中十种一步拷贝数组的方法实例详解
Apr 22 Javascript
JS实现从对象获取对象中单个键值的方法示例
Jun 05 Javascript
vue transition 在子组件中失效的解决
Nov 12 Javascript
JS实现基本的网页计算器功能示例
Jan 16 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实现的http请求封装示例
2016/11/08 PHP
javascript中的变量是传值还是传址的?
2010/04/19 Javascript
jqeury eval将字符串转换json的方法
2011/01/20 Javascript
jquery(live)中File input的change方法只起一次作用的解决办法
2011/10/21 Javascript
JS格式化数字保留两位小数点示例代码
2013/10/15 Javascript
js与jquery获取父级元素,子级元素,兄弟元素的实现方法
2014/01/09 Javascript
js 立即调用的函数表达式如何写
2014/01/12 Javascript
分享一个自己动手写的jQuery分页插件
2014/08/28 Javascript
JavaScript实现三阶幻方算法谜题解答
2014/12/29 Javascript
jQuery+ajax实现动态执行脚本的方法
2015/01/27 Javascript
JavaScript数组去重的五种方法
2015/11/05 Javascript
谈谈encodeURI和encodeURIComponent以及escape的区别与应用
2015/11/24 Javascript
基于javascript实现图片懒加载
2016/01/05 Javascript
原生JS实现的放大镜效果实例代码
2016/10/15 Javascript
Bootstrap 模态框(Modal)带参数传值实例
2017/08/20 Javascript
bootstrap3中container与container_fluid外层容器的区别讲解
2017/12/04 Javascript
JS设计模式之命令模式概念与用法分析
2018/02/06 Javascript
详解vue组件开发脚手架
2018/06/15 Javascript
vue 动态组件(component :is) 和 dom元素限制(is)用法说明
2020/09/04 Javascript
js实现购物车商品数量加减
2020/09/21 Javascript
pymongo给mongodb创建索引的简单实现方法
2015/05/06 Python
Python更新数据库脚本两种方法及对比介绍
2017/07/27 Python
Python字符串、整数、和浮点型数相互转换实例
2018/08/04 Python
python pandas库的安装和创建
2019/01/10 Python
Python实现图片裁剪的两种方式(Pillow和OpenCV)
2019/10/30 Python
Python 实现将数组/矩阵转换成Image类
2020/01/09 Python
无畏的旅行:Intrepid Travel
2017/12/20 全球购物
高清安全摄像头系统:Lorex Technology
2018/07/20 全球购物
美国户外运动商店:Sun & Ski
2018/08/23 全球购物
Allsole美国/加拿大:英国一家专门出售品牌鞋子的网站
2018/10/21 全球购物
青春励志演讲稿
2014/04/29 职场文书
2015年社区妇联工作总结
2015/04/21 职场文书
欢送会主持词
2015/07/01 职场文书
环境卫生标语
2015/08/03 职场文书
position:sticky 粘性定位的几种巧妙应用详解
2021/04/24 HTML / CSS
MIME类型中application/xml与text/xml的区别介绍
2022/01/18 HTML / CSS