红宝书笔记——JavaScript 面向对象

433 阅读3分钟

属性类型

要修改对象的属性的默认的特性,必须使用Object.defineProperty() 方法。这个方法接受三个参数:属性所在的对象,属性的名字,一个描述符对象。
描述符对象的属性必须是configurable,enumberable,writable,value。在不指定情况下,configurable,enumberable,writable这三个属性都是默认为false。
configurable设置为false 表示不能从对象中删除属性。writable设置为false表示是只读的,不能对属性进行赋值。enumberable表示能否通过for-in循环返回属性。

访问器属性

在读取访问器属性时,会调用getter函数;在写入访问器属性时,会调用setter函数并传入新值。 访问器属性不能直接定义,必须使用Object.defineProperty()来定义。

var book={
    _year:2004,
    edition:1
};
Object.defineProperty(book,"year",{
    get:function(){
        return this._year;
    },
    set:function(newValue){
        if(newValue>2004){
            this._year=newValue;
            this.edition+=newValue-2004;
        }
    }
});
book.year=2005;
alert(book.edition);//2

定义多个属性:Object.defineProperties()方法。
读取属性的特征:Object.getOwnPropertyDescriptor()方法。

var book={
};
Object.defineProperties(book,{
    _year:{
        value:2004,
        writable: true//这个必须写,不然不能下面book.year没有启用而起作用弹出2007,不然就弹出2004
    },
    edition:{
        value:1
    },
    year:{
        get:function(){
            return this._year;
        },
        set:function(newValue){
            if(newValue>2004){
                this._year=newValue;
                this.edition+=newValue-2004;
            }
        },
    }
});
var descriptor=Object.getOwnPropertyDescriptor(book,"_year");
alert(descriptor.value);//2004
alert(descriptor.configurable);//false
book.year=2007;
alert(book._year);//2007

创建对象

1.工厂模式:

function createPerson(name,age,job){
    var o=new Object();
    o.name=name;
    o.age=age;
    o.job=job;
    o.sayName=function(){
        alert(this.name);
    };
    return o;
}
var person1=createPerson("Nick",29,"Engineer");
var person2=createPerson("Greg",27,"Doctor");
person1.sayName();//Nick
alert(person2.name);//Greg

2.构造函数模式:

function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.sayName=function(){
        alert(this.name);
    }
}
var person1=new Person("Nick",29,"Engineer");
var person2=new Person("Greg",27,"Doctor");
person1.sayName();//Nick
alert(person2.name);//Greg

3.原型模式

function Person(){
}
Person.prototype.name="Nike";
Person.prototype.age=29;
Person.prototype.job="Engineer";
Person.prototype.sayName=function(){
    alert(this.name);
};
var person1=new Person();
person1.sayName();//Nike
var person2=new Person();
person2.sayName();//Nike
alert(person1.sayName==person2.sayName);//true

// 自定义hasPrototypeProperty
function hasPrototypeProperty(obj, property) {
    return !obj.hasOwnProperty(property) && property in obj
}

hasOwnProperty() 方法可以检测一个属性是否存在于实例中,还是存在于原型中。如果存在于对象实例中,则返回true。
hasPrototypeProperty() 方法可以检测一个属性是否存在于实例中,还是存在于原型中。如果存在于对象原型中,则返回true。
Object.keys() 方法接受一个对象作为参数,返回一个包含所有可枚举属性的字符串数组。

更简单的原型语法:

function Person(){
}
Person.prototype={
  name: "Nike",
  age: 29,
  job: "Engineer",
  sayName: function(){
    alert(this.name);
  }
};

原型对象的问题:

function Person(){
}
Person.prototype={
  constructor: Person,
  name: "Nike",
  job: "Engineer",
  friends: ["Shelby","Court"],
  sayName: function(){
    alert(this.name);
  }
};
var person1=new Person();
var person2=new Person();
person1.friends.push("Van");
alert(person1.friends);//Shelby,Court,Van
alert(person2.friends);//Shelby,Court,Van
alert(person1.friends==person2.friends);//true

可以看到当改变一个对象的friends时,其他的对象的friends也跟着改变friends数组存在于person.prototype中,而不是存在于person1中,所以当改变person1的friends时候,person2的friends也变化。

4.组合使用构造函数模式和原型模式:构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。

function Person(name,age,job){
  this.name=name;
  this.age=age;
  this.job=job;
  this.friends=["Shelby","Court"];
}
Person.prototype={
  constructor: Person,
  sayName: function(){
    alert(this.name);
  }
}
var person1=new Person("Nike",29,"Engineer");
var person2=new Person("Greg",27,"Doctor");
person1.friends.push("Van");
alert(person1.friends);//Shelby,Court,Van
alert(person2.friends);//Shelby,Court
alert(person1.friends==person2.friends);//false
alert(person1.sayName==person2.sayName);//true

5.动态原型模式
可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    if(typeof this.sayName != "function") { //在sayName()方法不存在的情况下,才会将它添加到原型中。instanceof操作符也可以
        Person.prototype.sayName = function() {
            alert(this.name);
        };
    }
}
var friend = new Person("Nike", 29, "Engineer");
friend.sayName();//Nike