zoukankan      html  css  js  c++  java
  • JS 创建对象的7种方法(二)

    3.原型模式(Prototype)

    我们创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象。使用原型对象的好处是让所有实例共享它所包含的属性和方法。

    function Person(){
    
    }
    Person.prototype.name = "Bob";
    Person.prototype.age = 18;
    Person.prototype.job = "Developer";
    Person.prototype.sayName = function(){
        alert(this.name);
    }
    
    var person1 = new Person();
    var person2 = new Person();

    3.1 理解原型对象

    只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会获得一个constructor属性,这个属性指向prototype属性所在的函数。

    当调用构造函数创建一个新实例后,该实例的内部包含一个指针(内部属性--[[Prototype]]),指向构造函数的原型对象。 虽然我们无法访问到[[Prototype]],但可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系。如果[[Prototype]]指向调用isPrototypeOf()方法的对象,那么这个方法就返回true。

    alert(Person.prototype.isPrototypeOf(person1));    //true
    alert(Person.prototype.isPrototypeOf(person2));    //true

    Object.getPrototypeOf()方法返回[[Prototype]]的值:

    alert(Object.getPrototypeOf(person1) == Person.prototype);   //true
    alert(Object.getPrototypeOf(person1).name);    //Bob

    每当代码读取某个对象的属性时,都会执行一次搜索。搜索首先从对象实例本身开始,如果在实例中找到了,则返回该属性的值;如果没有找到,则继续搜索指针指向的原型对象。

    我们可以通过对象实例访问保存在原型中的值,但不能通过对象实例改变原型中的值:

    person1.name = "Peter";
    person1.sayName();    //"Peter" 来自实例
    person2.sayName();    //"Bob"   来自原型

    使用hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中。接上面的例子:

    alert(person1.hasOwnProperty("name"));    //true  
    alert(person2.hasOwnProperty("name"));    //false
    alert(person1.hasOwnProperty("age"));       //false
        

    3.2 原型与in操作符

     in操作符会在 通过对象能访问属性时返回true, 无论该属性存在于实例中还是原型中。

    alert("name" in person1);    //true 来自实例
    alert("name" in person2);    //true 来自原型

    同时使用hasOwnProperty()方法与in操作符,就可以确定该属性的位置。

    function hasPrototypeProperty(object, name){
        return !object.hasOwnProperty(name) && (name in object);        
    }
    alert(hasPrototypePropoty(person1, "name"));  //false
    alert(hasPrototypePropoty(person2, "name")); //true

    使用Object.keys()方法可以取得对象上所有可枚举的实例属性:

    var keys = Object.keys(Person.prototype);
    alert(keys);     //name, age, title, sayName
    var keys1 = Object.keys(person1);
    alert(keys1);  //name

    Object.getOwnPropertyNames() 可以或得所有实例属性(包括不可枚举的)

    alert(Object.getOwnPropertyNames(Person.prototype));    //constructor,name,age,title,sayName

    3.3 更简单的原型方法

    function Person(){
    }
    
    Person.prototype = {
        name: "Bob",
        age: 29,
        title: "Developer",
        sayName: function(){
            alert(this.name);
        }
    };

     在上面的例子中,我们将Person.prototype设置为等于一个以对象字面量形式创建的新对象。最终结果相同,但constructor属性不再指向Person。上面的例子本质上重写了默认的prototype对象,因此constructor属性也就变成了新对象的constructor属性(指向Object构造函数)。

    3.4原型对象的问题

      1. 原型模式省略了为构造函数传递参数,所以所有实例在默认情况下都取得相同的属性值。

      2. 对于引用类型值:

    function Person(){
    }
    
    Person.prototype = {
        name: "Bob",
        age: 29,
        title: "Developer",
        friends:["Court", "Ann"],
        sayName: function(){
            alert(this.name);
        }
    }; 
    
    var person1 = new Person();
    var person2 = new Person();
    
    person1.friends.push("Alice");
    
    alert(person1.friends);    // Court, Ann, Alice
    alert(person2.friends);    // Court, Ann, Alice
  • 相关阅读:
    第二章 关系模型介绍
    第一章 引言
    只要人人都献出一点爱......
    小算法
    题目:返回一个整数数组中最大子数组的和。
    题目:返回一个整数数组中最大子数组的和
    梦断代码读后感之开始篇
    电梯调度需求分析
    结对开发--求二维数组的最大子数组
    四则运算(3)--答题小系统
  • 原文地址:https://www.cnblogs.com/PrajnaParamita/p/5750507.html
Copyright © 2011-2022 走看看