JS 对象封装的常用方式

JS是一门面向对象语言,其对象是用prototype属性来模拟的。来看看如何封装JS对象.

常规封装

function Person (name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
} Pserson.prototype = {
constructor:Person,
sayHello:function(){
console.log('hello');
}
}

这种方式是比较常见的方式,比较直观,但是Person() 的职责是构造对象,如果把初始化的事情也放在里面完成,代码就会显得繁琐,如果放在一个方法里初始化会不会好点呢?

升级版 (常见)

function Person (info){
this._init_(info);
} Pserson.prototype = {
constructor : Person,
_init_ : function(info) {
this.name = info.name;
this.age = info.age;
this.sex = info.sex;
}
sayHello:function(){
console.log('hello');
}
}

可是,说到这里就发现,name,age,sex 并没有在Person里面申明,哪来的呢???

new 的执行原理

new 的执行过程可以用下面一个函数来代替

 var myNew = function(constructor, args) {
var o = {};
o.__proto__ = constructor.prototype;
var res = constructor.apply(o, args);
var type = typeof res;
if (['string', 'number', 'boolean', 'null', 'undefined'].indexOf(type) !== -1) {
return o;
}
return res;
}

解释:
首先通过 var o = {} 构造一个空对象.
然后将 构造函数的原型属性prototype赋值给o 的原型对象__proto__ 。这样,在执行 this.init(info); 这句话的时候,对象 o 就可以在其原型对象中查找_init_ 方法。(原型链)。
之后这句话 就是精髓了。

var res = constructor.apply(o,args);

以o为上下文调用函数,同时将参数作为数组传递。那么,

 this._init_(info);

这句话就会被 o 执行,函数

 _init_ : function(info) {
this.name = info.name;
this.age = info.age;
this.sex = info.sex;
}

以 o 为上下文调用,o也将拥有自己的 name,age,sex 属性。

如果在构造函数中,return 复合类型,包括对象,函数,和正则表达式,那么就会直接返回这个对象,否则,返回 o

var type = typeof res;
if(['string','number','boolean','null','undefined'].indexOf(type) !== -1){
return o;
}
return res;

测试一下

   function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(this.name);
}
var o1 = myNew(Person, ['pawn']);
console.log(o1);
o1.sayHello();

call方法:
语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]])

定义:调用一个对象的一个方法,以另一个对象替换当前对象。

说明:

call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

apply方法:

语法:apply([thisObj[,argArray]])

定义:应用某一对象的一个方法,用另一个对象替换当前对象。

说明:

如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。

如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。

类jQuery 封装

这种方式是我从 jQuery 那里学来的。

jQuery 对象具有很强的集成性,可以作为函数调用,也可以做为对象调用,当作为函数调用的时候,她可以无需 new 而返回它的一个实例,很方便。

代码

var Person = function(info){
return new Person.prototype.init(info);
} Person.prototype = {
constructor: Person,
init:function(){
this.name = info.name.
}
}
Person.prototype.init.prototype = Person.prototype;

这种封装方式非常巧妙。
将对象的构造操作放在函数的里面,而自己充当一个工厂。
不断调用 prototype 并不是一个直观的做法,于是

var Person = function(info){
return new Person.fn.init(info);
} Person.fn = Person.prototype = {
constructor: Person,
init:function(){
this.name = info.name;
this.sayHello = function(){
this.makeArray();
}
}
makeArray:function(){
console.log(this.name);
}
}
// 这句话的作用
// 虽然把makeArray 等常用方法挂载到 Person.prorotype 下面,但还是会被 init 这个实例使用.
Person.fn.init.prototype = Person.fn;

最后用 闭包 封装起来

var Person = (function(window) {
var Person = function(name) {
return new Person.fn.init(name);
} Person.fn = Person.prototype = {
constructor: Person,
init: function(name) {
this.name = name;
this.sayHello = function() {
this.makeArray();
}
},
makeArray: function() {
console.log(this.name);
}
} Person.fn.init.prototype = Person.fn; return Person;
})();

测试一下

 var p = Person('pawn');
console.log(p);
p.sayHello();

object.create()

js也提供了一种构造对象的方式,object.create(); 可以传递一个对象Person,构造一个p,并且使p 继承Person.

  var Person = {
name: 'pawn',
sayHello: function() {
console.log(this.name);
}
}
var p = Object.create(Person);
console.log(p);
p.sayHello();

可以看到,对象Person的属性成为了p的原型属性,也就是说 p 原型继承自 Person !

我们可以实现一个 Object.create()

Object.create = function(prototype){
function Func(){};
Func.prototype = prototype;
var o = new Func();
return o;
}

在这里,我们将 Person 作为 构造函数的 原型属性,就可以构造出 以Person 为原型对象的对象.

JavaScript封装的几种方式的更多相关文章

  1. JavaScript 创建对象的七种方式

    转自:xxxgitone.github.io/2017/06/10/JavaScript创建对象的七种方式/ JavaScript创建对象的方式有很多,通过Object构造函数或对象字面量的方式也可以 ...

  2. JavaScript创建对象的几种 方式

    //JavaScript创建对象的七种方式 //https://xxxgitone.github.io/2017/06/10/JavaScript%E5%88%9B%E5%BB%BA%E5%AF%B9 ...

  3. [转载]javascript创建对象的几种方式

    原文链接:http://qingfeng825.iteye.com/blog/1935648 1. 工厂方法:能创建并返回特定类型对象的工厂函数(factory function). function ...

  4. JavaScript事件处理的三种方式(转)

    一.什么是JavaScript事件? 事件(Event)是JavaScript应用跳动的心脏,也是把所有东西粘在一起的胶水,当我们与浏览器中Web页面进行某些类型的交互时,事件就发生了. 事件可能是用 ...

  5. 总结javascript继承的两种方式的N中写法

    最近翻看博客园,总结了一下javascript的继承方式:prototype和copy继承方式. 一.prototype方式 当一个函数被创建时,Function构造函数产生的函数会隐式的被赋予一个p ...

  6. javascript实现继承3种方式: 原型继承、借用构造函数继承、组合继承,模拟extends方法继承

    javascript中实现继承的三种方式:原型继承.借用构造函数继承.混合继承: /* js当中的继承 js中 构造函数 原型对象 实力对象的关系: 1 构造函数.prototype = 原型对象 2 ...

  7. Flex(ActionScript)与JavaScript交互的两种方式示例

    随着各单位部门信息化进程的不断发展,互通互联.共享协调不断的被越来越多的客户所重视.很多新项目都要去必须能够集成已有的早期系统,至少也要能够实现交互对接.今天跟大家分享的是系统对接中ActionScr ...

  8. Struts2框架的数据封装一之属性封装(属性封装的第二种方式:封装成javaBean)

    Struts2中提供了两类数据封装的方式? 第一种方式:属性驱动(有两种方式:一个对属性,另外一个是将参数封装到javaBean中) B. 在页面上,使用OGNL表达式进行数据封装.(将参数封装到ja ...

  9. Struts2框架的数据封装一之属性封装(属性封装的第一种方式:对参数进行封装)

    request带着参数来,aciton对其进行处理.在学习action之前,使用的是servlet对request进行处理.request请求时会带有参数,所以我们要对这些参数进行封装. 1. 为什么 ...

随机推荐

  1. hdu-----(4514)湫湫系列故事——设计风景线(树形DP+并查集)

    湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tot ...

  2. 关于 iOS 批量打包的总结

      关于 iOS 批量打包的总结 本文作者: 伯乐在线 - Tsui YuenHong .未经作者许可,禁止转载!欢迎加入伯乐在线 专栏作者. 如果你曾经试过做多 target 的项目,到了测试人员要 ...

  3. poj1258 Agri-Net (prim+heap)

    题目链接:poj1258 Agri-Net 这题我上个月做过,是个大水题,今天看见有人用prim+heap做的,就学习了下. #include<cstdio> #include<cs ...

  4. poj2676 Sudoku(DFS)

    做了很久还是参考了别人的答案orz,其实也不难啊.我要开始学一下怎么写搜索了... 题目链接:poj2676 Sudoku 题解:暴力搜索,DFS每个空白格子所放数字. #include<cst ...

  5. css中的zoom

    CSS中zoom:1的作用兼容IE6.IE7.IE8浏览器,经常会遇到一些问题,可以使用zoom:1来解决,有如下作用:触发IE浏览器的haslayout解决ie下的浮动,margin重叠等一些问题. ...

  6. 421. Maximum XOR of Two Numbers in an Array——本质:利用trie数据结构查找

    Given a non-empty array of numbers, a0, a1, a2, - , an-1, where 0 ≤ ai < 231. Find the maximum re ...

  7. ES mlockall作用——preventing that memory from being paged to the swap area

    elasticsearch还有一个重要的参数bootstrap.mlockall,这个参数的目的是当你无法关闭系统的swap的时候,建议把这个参数设为true.防止在内存不够用的时候,elastics ...

  8. boost 源码编译 的 Makefile.am写法备份

    include $(top_srcdir)/common.mk bin_PROGRAMS= lib_LIBRARIES= lib_LTLIBRARIES= lib_LTLIBRARIES+=libSt ...

  9. PHP获取汉字的转化为拼音字母实现程序

    一个完整的php获取汉字拼音字母的实现程序,有需要的朋友可参考一下. <?php class GetPingYing { private $pylist = array( 'a'=>-20 ...

  10. HDU 4627 E(Contest #3)

    Description There are many unsolvable problem in the world.It could be about one or about zero.But t ...