资讯专栏INFORMATION COLUMN

JS对象之封装(二)

jasperyang / 1032人阅读

摘要:对象封装的常用方式常规封装升级版较常见的执行原理解释说明通过构造一个空对象将构造函数的原型属性赋值给的原型对象在执行这句话的时候,对象就可以在其原型对象中查找方法。

JS 对象封装的常用方式

1.常规封装

    function Person (name,age){ 
        this.name = name;
        this.age = age;
    }
    
    Pserson.prototype = {
       constructor:Person,
       say:function(){
           console.log("hello everyone!");
     }
    }

2.升级版 (较常见)

    function Person (example){
        this._init_(example);
    }
    Pserson.prototype = {
        constructor : Person,
        _init_ : function(example) {
            this.name = example.name;
            this.age = example.age;
        }
        say:function(){
            console.log("hello everyone");
        }
    }

3.new 的执行原理

var myNew = function(constructor, args) {
    var obj = {};
    obj .__proto__ = constructor.prototype;
    var res = constructor.apply(obj , args);
    var type = typeof res;
    if (["string", "number", "boolean", "null", "undefined"].indexOf(type) !== -1) {
        return obj ;
    }
    return res;
}
解释说明: 通过var obj = {} 构造一个空对象. 将构造函数的原型属性prototype赋值给obj 的原型对象__proto__
,在执行 this.init(example); 这句话的时候,对象 obj 就可以在其原型对象中查找_init_ 方法。(原型链)。
var res = constructor.apply(obj,args);

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

this._init_(example);

就会被 obj 执行

函数

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

以 obj 为上下文调用,o也将拥有自己的 name,age属性。
如果在构造函数中,return 复合类型,包括对象,函数,和正则表达式,那么就会直接返回这个对象,否则,返回 obj

var type = typeof res;

if(["string","number","boolean","null","undefined"].indexOf(type) !== -1){
    return obj;
}
return res;

举例

   function Person(name) {
        this.name = name;
    }
    Person.prototype.say = function() {
        console.log(this.name);
    }
    var jack = myFriend(Person, ["jack "]);
    console.log(jack );
    jack.say();

4.类jQuery 封装

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

代码

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

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

    var Person = function(example){
            return new Person.fn.init(example);
        }
    
    Person.fn = Person.prototype = {
        constructor: Person,
        init:function(){
            this.name = info.name;
            this.say = function(){
                this.makeExp();
            }
        }
        makeExp:function(){
            console.log(this.name);
        }
    }

// 虽然把makeArray 等常用方法挂载到 Person.prorotype 下面,但还是会被 init 这个实例使用.
Person.fn.init.prototype = Person.fn;
最后用 闭包 封装起来

 var Person = (function(win) {
        var Person = function(name) {
            return new Person.fn.init(name);
        }

        Person.fn = Person.prototype = {
            constructor: Person,
            init: function(name) {
                this.name = name;
                this.say = function() {
                    this.makeExp();
                }
            },
            makeExp: function() {
                console.log(this.name);
            }
        }

        Person.fn.init.prototype = Person.fn;

        return Person;
    })()

举例:

var people = Person("jack");
console.log(people);
people.say();

object.create();
一种构造对象的方式, 可以传递一个对象Person,构造一个people,并且使people 继承Person.

var Person = {
    name: "jack",
    say: function() {
        console.log(this.name);
    }
}
var people = Object.create(Person);
console.log(people);
people.say();

对象Person的属性成为了people的原型属性,也就是说 people 原型继承自 Person !

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

Object.create = function(prototype){
   function Fun(){};
   Fun.prototype = prototype;
   var obj = new Fun();
   return obj;
}

说明:
将 Person 作为 构造函数的 原型属性,就可以构造出 以Person 为原型对象的对象.

Object.create(原型); 创建一个继承该原型的实例对象

关于此方法的一些注意事项:
(1)若传参为Object.prototype,则创建的原型为Object.prototype,

和 new Object()创建的对象是一样的 Object.create(Object.prototype) <==>new
Object();

(2)若传参为空 或者 null,则创建的对象是没有原型的,

导致该对象是无法用document.write()打印会报错,

因为document.write()打印的原理是调用Object.prototype.toString()方法,   
该对象没有原型,也就没有该方法,所以document.write()无法打印
   由此延伸的知识点: 引用值都也是算作是对象,  所以都可以用document.write()打印; 原始值numebr, boolean,
   string都有自己对象的包装类, 借助此机制也是可以用document.write()打印出的;

  但undefined 和 null既不是引用值,也没有对应的包装类,    所以应该无法打印的,但大家会发现这两个值也是可是用document.write()打印的, 因为这两个值被设定为特殊值,   

document.write()打印其是不用调用任何方法的,而是之直接打印其值

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95036.html

相关文章

  • JS对象封装

    摘要:对象封装的常用方式常规封装升级版较常见的执行原理解释说明通过构造一个空对象将构造函数的原型属性赋值给的原型对象在执行这句话的时候,对象就可以在其原型对象中查找方法。 JS 对象封装的常用方式 1.常规封装 function Person (name,age){ this.name = name; this.age = age; } ...

    jk_v1 评论0 收藏0
  • JS对象封装

    摘要:对象封装的常用方式常规封装升级版较常见的执行原理解释说明通过构造一个空对象将构造函数的原型属性赋值给的原型对象在执行这句话的时候,对象就可以在其原型对象中查找方法。 JS 对象封装的常用方式 1.常规封装 function Person (name,age){ this.name = name; this.age = age; } ...

    codergarden 评论0 收藏0
  • JS 设计模式封装

    摘要:闭包实现封装类静态变量静态方法正整数私有属性年龄不是一个正整数一个只能创建个人测试静态变量测试封装效果测试静态函数主要参考设计模式的例子总结可以看到这样实现了封装效果。 什么是封装 封装就是把一个对象保护起来,使其只提供定义的接口方法,而保护私有的变量。打个比方,游戏中的一个人物对象,它的经验只有通过打死怪兽这个接口方法来增加。如果可以直接修改经验就会直接影响到整个游戏的设定。所以这个...

    SunZhaopeng 评论0 收藏0
  • 你不能不知道的Koa实现原理

    摘要:前言什么这是一篇源码解读文章那一定很枯燥不看。通过利用函数,帮你丢弃回调函数,并有力地增强错误处理。并没有捆绑任何中间件,而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。 showImg(https://segmentfault.com/img/bVNQYf?w=1020&h=790); 前言 什么?这是一篇源码解读文章 ? 那一定很枯燥!不看。 我把 Koa 的核心实...

    LinkedME2016 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<