学习笔记:对象,原型和继承(1)

一:建立对象
1 工厂模式函数

function createPerson(name, age, jod){
     var obj = new Object();
     obj.name = name;
     obj.age = age;
     obj.job = job;
     obj.sayName = function(){
         console.log(this.name);
     };
     return obj;
 }

 var person1 = createPerson('NEVAR', 23, 'Front-end Engineer');
 var person2 = createPerson('Amy', 27, 'Doctor');

2 构造函数模式this

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

 var person1 = new Person('NEVAR', 23, 'Front-end Engineer');
 var person2 = new Person('Amy', 27, 'Doctor');
 //person1和person2都是Person的不一样实例。
 alert(person1.constructor == Person); //true
 alert(person2.constructor == Person); //true
 //便是Object的实例也是Person的实例
 alert(person1 instanceof Object); //true
 alert(person1 instanceof Person); //true
 //构造函数产生的是两个不一样实例,同名函数是不相等的
 alert(person1.sayName == person2.sayName); //false

3 原型模式prototype

function Person(){
 }

 Person.prototype.name = 'NEVAR';
 Person.prototype.age = 23;
 Person.prototype.job = 'Front-end Engineer';
 Person.prototype.sayName = function(){
     console.log(this.name);
 };

 var person1 = new Person();
 person1.sayName(); //NEVAR

 var person2 = new Person();
 person2.sayName; //NEVAR

 console.log(person1.sayName == person2.sayName);// true

 var person3 = new Person();
 person3.name = 'PP';
 console.log(person3.name); //PP 来自实例

 delete person3.name;
 console.log(person3.name); //NEVAR 来自原型

 alert(person1.hasOwnProperty("name")); //false 来自原型
 alert(person3.hasOwnProperty("name")); //true  来自实例

 alert("name" in person1); //true in操做符的使用

 function hasPrototypeProperty (obj, name){
     return !obj.hasOwnProperty(name) && (name in obj)
 }
 //判断属性来自实例 真 而后取反 
 //而且name属性存在于obj原型链上 说明这个 属性是属于prototype的

 alert(hasPrototypeProperty(person1,'name')) // true
 alert(hasPrototypeProperty(person3,'name')) // false

 alert(Object.keys(Person.prototype)) //"name,age,job,sayName" 
 //Person的可枚举属性

不过以上方法太过于麻烦 每次都要写重复的prototypecode

function Person(){
 }

 Person.prototype = {
     name : 'NEVAR',
     age : '23',
     job : 'Front-end Engineer',
     sayName : function(){
         console.log(this.name);
     }
 };

constructor 属性再也不指向Person 了 指向Object对象

var friend = new Person();
 alert(friend instanceof Object); //true
 alert(friend instanceof Person); //true
 alert(friend.constructor == Person); //false
 alert(friend.constructor == Object); //true

因而能够这样原型链

Person.prototype = {
     constructor : Person,
     name : 'NEVAR',
     age : '23',
     job : 'Front-end Engineer',
     sayName : function(){
         console.log(this.name);
     }
 };

原型的动态性原型

var friend = new Person();

 Person.prototype.sayHi = function(){
     alert('Hi');
 }
friend.sayHi();//Hi
//这时没有问题,若是咱们重写原型对象 那么状况就不同了
function Person(){
}
var friend = new Person();
Person.prototype = {
constructor: Person,
name : "NEVAR",
age : 23,
job : "Front-end Engineer",
sayName : function () {
alert(this.name);
}
};
friend.sayName(); //error

重写原型对象切断了现有原型与任何以前已经存在的对象实例之间的联系;它们引用的仍然是最初的原型。io

原型模式也不是没有缺点。首先,它省略了为构造函数传递初始化参数这一环节,结果全部实例在默认状况下都将取得相同的属性值console

对于那些包含基本值的属性倒也说得过去,毕竟(如前面的例子所示),经过在实例上添加一个同名属性,能够隐藏原型中的对应属性。然而,对于包含引用类型值的属性来讲,问题就比较突出了function

function Person(){
}
Person.prototype = {
constructor: Person,
name : "Nicholas",
age : 29,
job : "Software 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

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(){
         console.log(this.name);
     }
 }

 var person1 = new Person('NEVAR', 23, 'Front-end Engineer');
 var person2 = new Person('Amy', 27, 'Doctor');

 person1.friends.push('Van');

 console.log(person1.friends) //'Shelby,Court,Van'
 console.log(person2.friends) //'Shelby,Court'
 console.log(person1.friends === person2.friends); // false
 console.log(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){
        Person.prototype.sayName = function(){
            console.log(this.name);
        }
    }
}

 var person1 = new Person('NEVAR', 23, 'Front-end Engineer');
 friend.sayName();

6寄生构造函数模式

//不使用this和new
function Person(name, age, job){
    //建立要返回的对象
    var o = new Object();
    //能够在这里添加私有变量和函数

    //添加方法
    o.sayName = function(){
        console.log(name);
    }
    return o;
}

注意,在以这种模式建立的对象中,除了使用sayName()方法以外,没有其余办法访问name 的值

相关文章
相关标签/搜索