zoukankan      html  css  js  c++  java
  • JavaScript 组件化开发之路(一)

    JavaScript中的对象属性

    深入了解JavaScript中的对象以及对象中的属性,是构建可复用组件的前提。

    对象的创建方式,常用的有两种:

    • 通过对象字面量创建

      var obj = {x:1}

    • 通过构造函数创建

      var obj = new Object()

    我们可以用for-in来遍历并输出对象的属性。

    var obj = {
        x: 1,
        y: 2,
        vars:['a','b','c'],
        add: function(){return this.x+this.y}
    }
    
    for(var prop in obj){
        console.log(prop)
    }
    //输出 x, y, vars,add
    

    在组件的开发中,我们经常要用到对象的继承,现在我们创建一个对象,它继承自obj,用es5里的方法,可以很容易的实现

    var obj2 = Object.create(obj)
    for(var prop in obj2){
        console.log(prop)
    }
    //输出 x, y, vars,add
    

    可以看到,obj2并没有自己的实例属性,但是,我们用for-in仍然可以得到三个属性。这三个属性继承自obj。 由于es5的这个方法并没有得到所有浏览器的支持,我们需要尝试自己实现对象的继承,去更加深入的了解继承的原理。

    var inherit = function(obj){
        function F(){}
        F.prototype = obj
        return new F()
    }
    
    var obj3 = inherit(obj)
    
    for(var prop in obj3){
        console.log(prop)
    }
    //x, y, vars,add
    

    看上去不错,我们也实现了所谓的继承,但是觉得似乎哪里有点不对劲?我们再创建一个对象试试

    var obj4 = inherit(obj)
    
    for(var prop in obj4){
        console.log(prop)
    }
    //x,y.vars,add
    

    我们试着操作obj3的属性

    obj3.x=0
    console.log(obj3.x) //0
    console.log(obj4.x) //1
    

    貌似没什么问题,继续

    obj.vars.push('d')
    console.log(obj3.vars) //["a", "b", "c", "d"]
    console.log(obj4.vars) //["a", "b", "c", "d"]
    

    出大事了。对一个对象的修改,影响到了另外一个对象。组件设计中,如果一个组件的修改,会影响到同类的其它实例,那还有什么独立性可言? 发生这种结果的原因, 就在我们实现的inherit方法中。在这个实现继承的方法中,我们首先创建了一个新的构造函数。这个构造函数的prototype指向了我们要继承的对象。因此,下面调用这个构造函数产生的对象,原型就是obj。当我们调用obj3.vars时,obj3本身并没有vars这个属性,于是它顺着原型链向上查找,在obj中找到了vars这个属性。这个属性的值是一个数组,数组属于引用类型,也就是说obj.vars属性中保存的只是一个指针(地址)。我们对obj3.vars得到的也是这个指针。针对这个指针指向的数组,进行了push操作,结果就是改变了这个指针指向的数组的值。当我们读取obj4的vars属性时,由于obj4本身也没有这个属性,它也会顺着原型链向上查找,找到obj.vars,而这时的obj.vars指向的数组已经被obj3的操作改变了。

    这种继承方式显然无法满足我们的需求。我们希望每个继承而来的对象,在享有共有属性和方法的同时,也有自己私有的一些属性和方法。这些私有的属性不应该被共享,也不可以被别的对象修改。

    下面是另一个实现继承的方式

    var myClass = function(){
        this.vars = ['a','b','c']
        this.x = 1
    }
    myClass.prototype.y=1
    myClass.prototype.say=function(){console.log('hi')}
    myClass.prototype.publicArr=[1,2,3]
    var my1 = new myClass
    var my2 = new myClass
    
    my1.vars.push('d')
    console.log(my1.vars) // ['a','b','c','d']
    console.log(my2.vars) // ['a','b','c']
    

    我们把每个对象的私有属性,定义在构造函数内部,而把那些需要共同享用的属性,放在构造函数的prototype属性中。这样,当我们创建对象时,每个对象都会拥有自己的私有属性(vars,x),也可以通过原型链,查找到原型中的属性。

    console.log(my1.y) //1
    my1.say() //'hi'
    console.log(my2.y) //2
    my2.say() //'hi'
    
    //共享的属性,可以被其它的对象改变
    my1.publicArr.push(4)
    console.log(my1.publicArr) //[1, 2, 3, 4]
    console.log(my2.publicArr) //[1, 2, 3, 4]
    
  • 相关阅读:
    Windows 8 C#调用C++编写的Windows运行时组件
    Metro style App Datetime formating.
    《编程匠艺》读书笔记之一
    ContextMenu的使用
    单例模式
    c# 类中字段属性设计
    Metro style app 文件查找
    Win 8 学习资料汇总
    Metro C++ 初体验 第二周
    Metro style app 文件、文件夹的选择、文件的保存。
  • 原文地址:https://www.cnblogs.com/zhangfengyang/p/5515915.html
Copyright © 2011-2022 走看看