简单理解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 Ajax 跨域访问的解决方案
Mar 12 Javascript
简洁短小的 JavaScript IE 浏览器判定代码
Mar 21 Javascript
JQUERY对单选框(radio)操作的小例子
Apr 25 Javascript
JS组件系列之Bootstrap table表格组件神器【终结篇】
May 10 Javascript
Angular2实现自定义双向绑定属性
Mar 22 Javascript
微信小程序实现皮肤功能(夜间模式)
Jun 18 Javascript
原生JavaScript来实现对dom元素class的操作方法(推荐)
Aug 16 Javascript
Vue导出json数据到Excel电子表格的示例
Dec 04 Javascript
详解swiper在vue中的应用(以3.0为例)
Sep 20 Javascript
微信小程序出现wx.getLocation再次授权问题的解决方法分析
Jan 16 Javascript
vue项目打包后怎样优雅的解决跨域
May 26 Javascript
laravel实现中文和英语互相切换的例子
Sep 30 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调用c接口无错版介绍
2014/03/11 PHP
什么情况下可以不写PHP的闭合标签“?>”
2014/08/28 PHP
PHP的pcntl多进程用法实例
2015/03/19 PHP
PHP实现获取某个月份周次信息的方法
2015/08/11 PHP
php慢查询日志和错误日志使用详解
2021/02/27 PHP
基于jQuery的投票系统显示结果插件
2011/08/12 Javascript
计算世界完全对称日的js代码,粗糙版
2011/11/04 Javascript
jquery 自定义容器下雨效果可将下雨图标改为其他
2014/04/23 Javascript
JavaScript数据类型之基本类型和引用类型的值
2015/04/01 Javascript
JavaScript的模块化开发框架Sea.js上手指南
2016/05/12 Javascript
jQGrid动态填充select下拉框的选项值(动态填充)
2016/11/28 Javascript
jQuery之动画ajax事件(实例讲解)
2017/07/18 jQuery
Vim快速合并行及vim 将文件所有行合并到一行
2017/11/27 Javascript
vue中使用ueditor富文本编辑器
2018/02/08 Javascript
javascript使用正则实现去掉字符串前面的所有0
2018/07/23 Javascript
原生JS实现获取及修改CSS样式的方法
2018/09/04 Javascript
vue+elementUi图片上传组件使用详解
2019/08/20 Javascript
JavaScript 严格模式(use strict)用法实例分析
2020/03/04 Javascript
Vue执行方法,方法获取data值,设置data值,方法传值操作
2020/08/05 Javascript
python实现保存网页到本地示例
2014/03/16 Python
python中sets模块的用法实例
2014/09/30 Python
Python中模拟enum枚举类型的5种方法分享
2014/11/22 Python
django多对多表的创建,级联删除及手动创建第三张表
2019/07/25 Python
python sorted函数的小练习及解答
2019/09/18 Python
python获取栅格点和面值的实现
2020/03/10 Python
Python自动化测试笔试面试题精选
2020/03/12 Python
Python实现区域填充的示例代码
2021/02/03 Python
Flask中jinja2的继承实现方法及实例
2021/03/03 Python
小学英语教学反思案例
2014/02/04 职场文书
法律七进实施方案
2014/03/15 职场文书
简单通用的简历自我评价
2014/09/21 职场文书
2014年小学生迎国庆65周年演讲稿
2014/09/27 职场文书
捐款通知怎么写
2015/04/24 职场文书
活动总结模板大全
2015/05/11 职场文书
无房证明样本
2015/06/17 职场文书
Redis特殊数据类型Geospatial地理空间
2022/06/01 Redis