zoukankan      html  css  js  c++  java
  • javascript对象封装的常用方式

    JS是门面向对象语言,其对象是用prototype属性来模拟的,下面例举下常用的封装方式。

    常规封装

     1 function Person(name, age, sex){
     2     this.name = name;
     3     this.age = age;
     4     this.sex = sex;
     5 }
     6 
     7 Person.prototype = {
     8     constructor: Person,
     9     sayHello: function(){
    10         console.log("hello");  
    11     }
    12 }    

    Person函数的职责是构造对象,如果把初始化的东西也放在里面,代码就会显得繁琐,于是有了升级版

    升级版

    function Person(info){
          this._init(info)
     }
    Person.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;
    }
    o.__proto__ = constructor.prototype;这句是将构造函数的原型属性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。

    类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并不是一个直观的做法,于是

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

    最后用闭包封装起来

    var Person = (function(window){
        var Person = function(name) {
            return new Person.fn.init(name);
        }
        Person.prototype = Person.fn = {
            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;
    })()    

    最后介绍一种object.create()构造对象的方式,可以传递一个对象Person,构造一个p,并且使p继承Person

    Person = {
         constructor: Person,
         sayHello: function(){
             console.log("hello");  
         }
    }    
    
    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为原型对象的对象。



  • 相关阅读:
    ps:图层知识
    ps:选区的存储及载入
    ps:消除锯齿和羽化
    ps:不规则选区
    ps:建立规则选区
    python如何查看内存占用空间
    python-生成器
    python3-列表生成式
    python:迭代
    Photoshop画笔工具的使用
  • 原文地址:https://www.cnblogs.com/fesf/p/7523709.html
Copyright © 2011-2022 走看看