简单理解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 相关文章推荐
ext读取两种结构的xml的代码
Nov 05 Javascript
javascript 隔行换色函数代码
Oct 24 Javascript
node.js发送邮件email的方法详解
Jan 06 Javascript
JavaScript之Canvas_动力节点Java学院整理
Jul 04 Javascript
详解react-native-fs插件的使用以及遇到的坑
Sep 12 Javascript
Angular实现预加载延迟模块的示例
Oct 12 Javascript
Bootstrap 3多级下拉菜单实例
Nov 23 Javascript
vue中axios解决跨域问题和拦截器的使用方法
Mar 07 Javascript
vue对storejs获取的数据进行处理时遇到的几种问题小结
Mar 20 Javascript
Angularjs 根据一个select的值去设置另一个select的值方法
Aug 13 Javascript
使用mpvue搭建一个初始小程序及项目配置方法
Dec 03 Javascript
vue中使用GraphQL的实例代码
Nov 04 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
为php4加入动态flash文件的生成的支持
2006/10/09 PHP
PHP实现AES256加密算法实例
2014/09/22 PHP
php中JSON的使用与转换
2015/01/14 PHP
php批量转换文件夹下所有文件编码的函数类
2017/08/06 PHP
一个JavaScript继承的实现
2006/10/24 Javascript
通过JAVASCRIPT读取ASP设定的COOKIE
2007/02/15 Javascript
JS操作Cookie写入和读取实例代码
2013/10/20 Javascript
web css实现整站样式互相切换
2013/10/29 Javascript
JavaScript设计模式之工厂方法模式介绍
2014/12/28 Javascript
简单介绍jsonp 使用小结
2016/01/27 Javascript
js获取隐藏元素宽高的实现方法
2016/05/19 Javascript
Node.js Express 框架 POST方法详解
2017/01/23 Javascript
jQuery实现一个简单的轮播图
2017/02/19 Javascript
深入理解jquery的$.extend()、$.fn和$.fn.extend()
2017/07/08 jQuery
bootstrap3-dialog-master模态框使用详解
2017/08/22 Javascript
js判断数组是否包含某个字符串变量的实例
2017/11/24 Javascript
Vue 实现双向绑定的四种方法
2018/03/16 Javascript
简单分析js中的this的原理
2019/08/31 Javascript
Python操作mysql数据库实现增删查改功能的方法
2018/01/15 Python
Django数据库表反向生成实例解析
2018/02/06 Python
PyQT实现多窗口切换
2018/04/20 Python
Python实现查看系统启动项功能示例
2018/05/10 Python
python上下文管理的使用场景实例讲解
2021/03/03 Python
基于PyTorch中view的用法说明
2021/03/03 Python
一款利用html5和css3实现的3D滚动特效的教程
2015/01/04 HTML / CSS
Mytheresa美国官网:德国知名的女性奢侈品电商
2017/05/27 全球购物
Eyeko美国:屡获殊荣的睫毛膏、眼线笔和眉妆
2018/07/05 全球购物
美丽的现代设计家具:2Modern
2018/07/26 全球购物
Nike瑞典官方网站:Nike.com (SE)
2018/11/26 全球购物
.NET初级开发工程师面试题
2014/04/18 面试题
中职生自荐信
2013/10/13 职场文书
学习全国两会精神心得体会范文
2014/03/17 职场文书
采购部长岗位职责
2014/06/13 职场文书
医生个人自我剖析材料
2014/10/08 职场文书
MySQL 数据表操作
2022/05/04 MySQL
Docker部署Mysql8的实现步骤
2022/07/07 Servers