简单理解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判断浏览器类型的代码
Nov 05 Javascript
js操纵跨frame的三级联动select下拉选项实例介绍
May 19 Javascript
js通过元素class名字获取元素集合的具体实现
Jan 06 Javascript
实例讲解使用原生JavaScript处理AJAX请求的方法
May 10 Javascript
JavaScript实现Fly Bird小游戏
Dec 15 Javascript
ES6概念 Symbol.keyFor()方法
Dec 25 Javascript
angular实现表单验证及提交功能
Feb 01 Javascript
Node.js调试技术总结分享
Mar 12 Javascript
vue cli 3.0 使用全过程解析
Jun 14 Javascript
vue2使用keep-alive缓存多层列表页的方法
Sep 21 Javascript
详解Axios统一错误处理与后置
Sep 26 Javascript
使用Vue实现调用接口加载页面初始数据
Oct 28 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部分常见问题总结
2006/10/09 PHP
用PHP调用Oracle存储过程的方法
2008/09/12 PHP
PHP 截取字符串 分别适合GB2312和UTF8编码情况
2009/02/12 PHP
PHP网站备份程序代码分享
2011/06/10 PHP
laravel 5.3中自定义加密服务的方案详解
2017/05/09 PHP
PHP实现动态压缩js与css文件的方法
2018/05/02 PHP
PHP 扩展Memcached命令用法实例总结
2020/06/04 PHP
用JavaScript将从数据库中读取出来的日期型格式化为想要的类型。
2009/08/15 Javascript
基于jquery实现状态限定编辑的代码
2012/02/11 Javascript
基于jQuery的获取标签名的代码
2012/07/16 Javascript
addEventListener和attachEvent二者绑定的执行函数中的this不相同
2012/12/09 Javascript
JavaScript中的连字符详解
2013/11/28 Javascript
JS实现的生成随机数的4个函数分享
2015/02/11 Javascript
js获取当前日期前七天的方法
2015/02/28 Javascript
js实现简单折叠、展开菜单的方法
2015/08/28 Javascript
Js与Jq获取浏览器和对象值的方法
2016/03/18 Javascript
BootStrap智能表单实战系列(九)表单图片上传的支持
2016/06/13 Javascript
javascript中this用法实例详解
2017/04/06 Javascript
JS实现判断有效的数独算法示例
2019/02/25 Javascript
详解appium+python 启动一个app步骤
2017/12/20 Python
Python实现调用另一个路径下py文件中的函数方法总结
2018/06/07 Python
Python 窗体(tkinter)按钮 位置实例
2019/06/13 Python
Python类中的魔法方法之 __slots__原理解析
2019/08/26 Python
用python打开摄像头并把图像传回qq邮箱(Pyinstaller打包)
2020/05/17 Python
如何解决pycharm调试报错的问题
2020/08/06 Python
Python如何读写CSV文件
2020/08/13 Python
详解Django自定义图片和文件上传路径(upload_to)的2种方式
2020/12/01 Python
Python如何使用神经网络进行简单文本分类
2021/02/25 Python
Rhone官方网站:男士运动服装、健身服装和高级运动服
2019/05/01 全球购物
意大利体育用品和运动服网上商店:Maxi Sport
2019/09/14 全球购物
阿里巴巴英国:Alibaba英国
2019/12/11 全球购物
旅游管理专业学生求职信
2013/09/28 职场文书
大学同学聚会邀请函
2014/01/29 职场文书
2014年党员公开承诺践诺书
2014/03/25 职场文书
体育运动会广播稿
2014/10/05 职场文书
门卫管理制度范本
2015/08/05 职场文书