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

相关图例:

原文地址:https://www.cnblogs.com/kinthon/p/4851910.html