JavaScript学习二-----JS对象一

1.私有变量和公有变量

function Obj(){
                var a=0; //私有变量
                var fn=function(){ //私有函数

                }
            }
//这样在函数对象Obj外部无法访问变量a和函数fn,它们就变成私有的,只能在Obj内部使用,即使是函数Obj的实例仍然无法访问这些变量和函数

 

function Obj(){
                this.a=0; //公有变量
                this.fn=function(){ //公有函数

                }
            }
//函数对象Obj在外部可以访问变量a和函数fn,实例化Obj也可以访问这些变量和函数。

 

2.静态变量

当定义一个函数后通过 “.”为其添加的属性和函数,通过对象本身仍然可以访问得到,但是其实例却访问不到,这样的变量和函数分别被称为静态变量和静态函数。

function Obj(){

            }

            Obj.a=0; //静态变量

            Obj.fn=function(){ //静态函数

            }

            console.log(Obj.a); //0
            console.log(typeof Obj.fn); //function

            var o=new Obj();
            console.log(o.a); //undefined
            console.log(typeof o.fn); //undefined

3.使用自定义构造函数模式创建对象。这种方式有个缺陷是sayName这个方法,它的每个实例都是指向不同的函数实例,而不是同一个。

function Person(name,age,job)
{
    this.name=name;
    this.age=age;
    this.job=job;
    this.sayName=function()
    {
        alert(this.name);
    };
}

var person = new Person("kevin",31,"SE");
person.sayName();

 这个对属性来说没有什么问题,但是对于方法来说问题就很大了,因为方法都是在做完全一样的功能,但是却又两份复制,如果一个函数对象有上千和实例方法,那么它的每个实例都要保持一份上千个方法的复制,这显然是不科学的,这可肿么办呢,prototype应运而生。

4.prototype属性

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,默认情况下prototype属性会默认获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针。

当创建了一个foo对象之后,设置它的原型链z为3.

 此时实例化对象obj,此时obj和foo的原型链都指向了prototype。为obj添加x,y属性,可以通过obj.z直接访问z属性。z属性其实不包含在实例化的obj中,但是却在obj对象的原型链上。当访问z属性的时候,在实例化中找不到对应z属性便会在它的原型链上寻找。但是通过obj.hasOwnProperty(obj.z);检测z是否是obj本身的属性。返回的是false,说明z不是obj的属性。

function foo(){};
    foo.prototype.z = 3;

    var obj = new foo();
    obj.x = 1;
    obj.y = 2;

 

 

根据上图可以看出Person对象会自动获得prototyp属性,而prototype也是一个对象,会自动获得一个constructor属性,该属性正是指向Person对象。

当调用构造函数创建一个实例的时候,实例内部将包含一个内部指针(很多浏览器这个指针名字为__proto__)指向构造函数的prototype,这个连接存在于实例和构造函数的prototype之间,而不是实例与构造函数之间。

function Person(name){
                this.name=name;
            }

            Person.prototype.printName=function(){
                alert(this.name);
            }

            var person1=new Person('Byron');
            var person2=new Person('Frank');

 

 

 5.使用原型模式创建对象;解决了方法3中提到的缺陷,使不同的对象的函数(如sayFriends)指向了同一个函数。但它本身也有缺陷,就是实例共享了引用类型friends,从下面的代码执行结果可以看到,两个实例的friends的值是一样的,这可能不是我们所期望的。

function Person()
{

}

Person.prototype = {
    constructor : Person,
    name:"kevin",
    age:31,
    job:"SE",
    friends:["Jams","Martin"],
    sayFriends:function()
    {
        alert(this.friends);
    }
};
var person1 = new Person();
person1.friends.push("Joe");
person1.sayFriends();//Jams,Martin,Joe
var person2 = new Person(); 
person2.sayFriends();//James,Martin,Joe

 6.组合使用原型模式和构造函数创建对象,解决了方法5中提到的缺陷,而且这也是使用最广泛、认同度最高的创建对象的方法。

function Person(name,age,job)
{
    this.name=name;
    this.age=age;
    this.job=job;
   this.friends=["Jams","Martin"];
}
Person.prototype.sayFriends=function()
{
    alert(this.friends);
};
var person1 = new Person("kevin",31,"SE");
var person2 = new Person("Tom",30,"SE");
person1.friends.push("Joe");
person1.sayFriends();//Jams,Martin,Joe
person2.sayFriends();//Jams,Martin

 7. 动态原型模式:这个模式的好处在于看起来更像传统的面向对象编程,具有更好的封装性,因为在构造函数里完成了对原型创建。这也是一个推荐的创建对象的方法。

function Person(name,age,job)
{
    //属性
    this.name=name;
    this.age=age;
    this.job=job;
    this.friends=["Jams","Martin"];
    //方法
    if(typeof this.sayName !="function")
    {
        Person.prototype.sayName=function()
        {
            alert(this.name);
        };
        
        Person.prototype.sayFriends=function()
        {
            alert(this.friends);
        };
    }
}

var person = new Person("kevin",31,"SE");
person.sayName();
person.sayFriends();

 

posted @ 2017-04-20 15:19  墨VS雪  阅读(162)  评论(0编辑  收藏  举报