zoukankan      html  css  js  c++  java
  • JavaScript之对象(一)

    JavaScript 自定义对象

      • 模式主要有工厂模式,构造函数方式,原型模式, 组合模式,动态原型模式; 
        例子:
    //工厂模式:对象识别问题,代码复用问题,无共享区域
    function createPerson(name, age) {
        var o = new Object();
        o.name = name;
        o.age = age;
        o.sayName = function() {
            alert(this.name);
        };
        return o;
    }
    //构造函数:代码复用问题,无共享区域
    function Person(name, age) {
        this.name = name;
        this.age = age;
        this.sayName = function() {
            alert(this.name);
        };
    }
    //原型模式: 对于函数来说可以,符合我们的要求,实现了共享;对于基本量来说,我们可以通过对实例新建一个同名的属性来得到实例变量;但是问题会出现引用类型,如果是引用类型的话,尽管也可以跟基本类型一样在实例 上新建一个同名的来覆盖,但在使用上就有些不合理(因为对象多半是有函数的),当我们直接在实例上调用了引用类型的方式时,其实是修改了原型中的对象。
    function Person() {
    }
    //使用prototype属性逐一添加
    var name = "Kin", age = 12;
    Person.prototype.name = name;
    Person.prototype.age = age;
    Person.prototype.sayName = function() {
        alert(this.name);
    }
    Person.prototype.friends = ["Mik", "Sell"];
    //利用对象字面量重写prototype Person.prototype = { constructor : Person, name : "Kin", age : 12, sayName : function() { alert(this.name); },
       friends : ["Mik", "Sell"]
    };
    //引用类型的问题在于,当我一个实例对象person1 调用了person1.friends.push("Jon")时,其实是修改原型中的friends,所以效果也就会出现在其他实例上了,当然我们可以直接复制(利用slice()来生成一个新的数组)并新建一个新的对象在person1上,也即person1.friends = person1.friends.slice(0, person1.friends.length).但这样往往比较麻烦,也容易忘记。
    //组合模式(组合使用构造函数和原型,不足是看起来不像是一个对象的定义方式)
    //定义实例变量
    function Person(name, age) {
        this.name = name;
        this.age = age;
        this.friends = ["shell", "dos"];
    }
    //定义类变量
    Person.prototype = {
        constructor : Person,
        sayName : function() {
        alert(this.name);
        }
    }
    //动态原型模式
    function Person(name, age) {
        this.name = name;
        this.age = age;
        if(typeof this.sayName != "function") {
            Person.prototype.sayName = function() {
                alert(this.name);
            };
            //other also here
        }
    }

    补充说明

      • 在function 中定义的实例变量(也就是用this指定的)在没有用new 实例化之前在内存中是不存在的。
      • 在函数创建之后(不用调用),该函数就会被创建一个prototype的属性(这个与在function中定义的不一样)。
      • 在利用构造函数实例化一个“对象”后,该对象会有一个[[prototype]]内部属性,这个属性的值是构造函数的原型对象的引用(也是因为这个机制才可以实现“类机制”和“继承机制”),但是我们无法直接访问这个属性,但在主流浏览器都支持实例化对象有一个“__proto__”属性,该属性值等于[[prototype]].
      • 在定义function后若是显示使用函数名去添加属性的话,此时的属性是已初始化的,也就是说在内存中分配了内存,但是这个内存区域的地址只有用函数名的引用才可以访问,而其实例对象是无法访问的;
      • 在javascript中是没有类的定义的,其实现主要:this来设定作用域(模仿实例对象),prototype来实现继承的方式
      • 在函数中定义的变量和函数如果是作为实例变量的,一定要用this.名称,否则会被解析器视为局部变量或是全局变量。
      • 其实JS的构造函数对于实例化对象而言,就是一个方法,一个去为自己添加属性的方法,在这个方法中可能会运用到一些局部变量(没有用this.*=*(*代表变量),那么这些变量在函数出栈后,就会被销毁。

    相关代码说明:

    function Person() {
        var test = "test"; //局部变量
        this.here = "here"; //实例变量
        this.sayAge = function() {
            return "age";
        };
    }
    console.log(Person.here); //undefined
    console.log(Person.sayAge()); //Person.sayAge is not a function
    //在外部定义
    Person.sayAge2 = function() {
        return "age";
    }
    Person.here2 = "outhere";
    console.log(Person.here2); //outhere
    console.log(Person.sayAge2()); //age
    Person.prototype = {
        constructor : Person,
        name : "Kin",
        age : 12,
        friends : ["Sell", "Mik"],
        sayName : function() {
            return "name";
        }
    }
    person1 = new Person();
    person2 = new Person();
    person1.sayAge2(); //person1.sayAge2 is not a function

    相关图例:

  • 相关阅读:
    利用相关的Aware接口
    java 值传递和引用传递。
    权限控制框架Spring Security 和Shiro 的总结
    优秀代码养成
    Servlet 基础知识
    leetcode 501. Find Mode in Binary Search Tree
    leetcode 530. Minimum Absolute Difference in BST
    leetcode 543. Diameter of Binary Tree
    leetcode 551. Student Attendance Record I
    leetcode 563. Binary Tree Tilt
  • 原文地址:https://www.cnblogs.com/kinthon/p/4851910.html
Copyright © 2011-2022 走看看