面向对象-原型对象

创建对象

Js中可以用构造函数模式创建对象,如:

    function Person(name, age, job) {

            this.name = name;

            this.age = age;

            this.job = job;

            this.sayName = function () {

                alert(this.name);

            }

        }

        var person1 = new Person("Nicholas", 29, "aa");

        var person2 = new Person("YU", 29, "BB");

这里应注意函数名首字母应大写,按照约定,构造函数始终都应该以一个大写字母开头,而非构造函数则应以一个小写字母开头。

原型对象

上述方法中,有一个缺点,就是对象中的sayName方法,每次都会重新new一个对象,因此,也就是说不同对象的sayName方法地址是不同的,然而这个方法都只是执行提示姓名,这种创建两个相同的function,完成同样的任务,确实没有必要。所以这存在了缺陷。使用下面的方法可以避免这种缺陷。

 function Person() {

        }

        Person.prototype.name = "YuKaifei";

        Person.prototype.age = 25;

        Person.prototype.job = "SoftWare";

        Person.prototype.sayName = function () {

            alert(this.name);

        }

        var person1 = new Person();

        person1.sayName();//YuKaifei

        var person2 = new Person();

        person2.sayName();  //YuKaifei

        alert(person1.sayName == person2.sayName); //true

理解原型对象

函数


Person


prototype


指向所对应的原型对象

函数的原型对象


Person  Prototype  (person的原型对象)


constructor


指向所对应函数(person)的指针


Name


“YuKaiFei”


Age


25


Job


“Soft Ware”


sayName


(function)

自定义函数1


Person1


prototype


指向所对应的原型对象

自定义函数2


Person2


prototype


指向所对应的原型对象

无论什么时候,只要创建了一个新函数,就会为该函数创建一个prototype属性,这个属性就指向所对应的原型对象。而默认情况下,原型对象的constructor属性会指向所对应函数的地址。也就是说这时这两个对象各有一个属性,是存放对方的地址的。

当调用一个构造函数创建一个新实例之后,该函数内部也有一个属性prototype,这个属性是执行原型对象的地址。也就是说新实例其实与构造函数并没有直接关系。

需要注意的是,新实例虽然没有属性和方法,但是却可以通过查找对象属性的方式来调用原型对象中的属性和方法。

当新的实例创建新的属性之后,如果和原型对象是相同的属性,那么在下次调用时会调用新实例的属性,而不是原型对象的属性。如:

        var person1 = new Person();

        person1.name="aaaa";

        var person2 = new Person();

        alert(person1.name);//aaaa

        alert(person2.name);//YuKaifei

in 操作符

有两种方式可以使用in,一种是单独in,一种是for-in,需要注意的是,无论该属性是存在于实例中还是存在于原型中,只要存在,就返回true。

例如 alert(name in person1)  返回true

for (var prop in person1) {

            if (prop == "name") {

                alert("name")

            }

        }

判断该属性是否存在实例中的方式是hasOwnPropery()方法。

例如:person1.hasOwnProperty(“Name”) 返回true

Person2.hasOwnProperty(“Name”) 返回false

获取对象上所有可枚举的实例属性:

 var keys = Object.keys(Person.prototype);

 alert(keys); //name,age,job,syName,注意keys是一个数组。

更简单的原型语法—存在缺陷

Person.prototype = {

            name: "Nicholas",

            age: 29,

            jon: "SowfWare",

            syaName: function () {

                alert(this.name);

            }

        }

可以使用这种方法更简单的创建原型,但需要注意的是,这种写法相当于重写了原型对象,所有consturctor属性是新的,即不在指向person。如:

function Person() {

        }

var friend = new Person();

        Person.prototype = {

            name: "Nicholas",

            age: 29,

            jon: "SowfWare",

            syaName: function () {

                alert(this.name);

            }

        }

        friend.sayName(); //error

上面代码会报错,原因在与重写了原型对象,指向丢失,也就是切断了现有原型与之前已经存在的对象之间的联系。如果避免这种方法可以在声明原型中指定: constructor:Person

原生对象的原型—String、Array

原型的模式体现在所有原生的引用类型,例如object、array、string等,都在其构造函数的原型上定义了方法,例如在Array.prototype中可以找到sort()方法,在string.prototype可以找到substring()方法。

通过原生对象的原型,不仅可以获得所有默认方法的引用,也可以随意的修改原生对象的原型,因此可以随时添加方法。例如:

为String添加一个名为startsWith() 方法。

String.prototype.startsWith = function (text) {

            return this.indexOf(text) == 0;

        }

        var msg = "Hello world!";

        alert(msg.startsWith("Hello")); //true

优化原型对象的缺陷

原型对象为了省略函数传递初始化这一环节,结果所有的实例在默认情况下都会取得相同的值,这对于值类型属性共享还可以,但是对于引用类型则会存在问题。如:

function Person() {

        }

   Person.prototype = {

            name: "Nicholas",

            age: 29,

            jon: "SowfWare",

            friends:["Yu","Kai"],

            syaName: function () {

                alert(this.name);

            }

        }

        var person1 = new Person;

        person1.name = "yy";

        var person2 = new Person;
        alert(person1.name); //yy

        alert(person2.name); //Nicholas

        person1.friends.push("Fei");

        alert(person1.friends); //YuKaiFei

        alert(person2.friends); //YuKaiFei

可以看到值类型并没有什么影响,但因为引用类型的特殊,所有实例的值都将会被改变。

所有最好采用动态原型模式

动态原型模式-声明原型的推荐方式

 function Person(name, age, job) {

            this.name = name;

            this.age = age;

            this.job = job;

            this.friends = ["Yu", "kai"];

            if (typeof  this.sayName != "function") {

                this.sayName = function () {

                    alert(this.name);

                };

            }

        }

        var f1 = new Person("Y", 29, "s");

        var f2 = new Person("Y", 29, "s");

        f1.friends.push("Fei");

        alert(f1.friends); //yu,kai,fei

        alert(f2.friends);//yu,kai
时间: 2024-11-08 23:49:12

面向对象-原型对象的相关文章

JS面向对象-原型对象,实例对象,构造函数的关系

JS中每创建一个函数,该函数就会自动拥有一个prototype属性,为什么那??  因为最根上的object拥有一个prototype属性,而js中所有的对象又都继承自object,所以js中所有的对象都拥有一个prototype属性,而在js中函数也是对象,所以js中每个函数也都有一个prototype属性. 例如:function Person(){...} 和function Dog(){...} 而每一个prototype属性又会获得一个constructor属性 该constructo

浅析JS原型对象&实例对象&构造函数(转)

浅析原型对象,实例对象,构造函数的关系 原文地址:JS面向对象-原型对象,实例对象,构造函数的关系(http://blog.csdn.net/u014205965/article/details/45798861) 因为最根上的object拥有一个prototype属性,而js中所有的对象又都继承自object,所以js中所有的对象都拥有一个prototype属性,而在js中函数也是对象,所以js中每个函数也都有一个prototype属性. 例如:function Person(){...} 和

javascript面向对象系列第一篇——构造函数和原型对象

× 目录 [1]构造函数 [2]原型对象 [3]总结 前面的话 一般地,javascript使用构造函数和原型对象来进行面向对象编程,它们的表现与其他面向对象编程语言中的类相似又不同.本文将详细介绍如何用构造函数和原型对象来创建对象 构造函数 构造函数是用new创建对象时调用的函数,与普通唯一的区别是构造函数名应该首字母大写 function Person(){ this.age = 30; } var person1 = new Person(); console.log(person1.ag

javascript面向对象——构造函数和原型对象

一般地,javascript使用构造函数和原型对象来进行面向对象编程,它们的表现与其他面向对象编程语言中的类相似又不同.本文将详细介绍如何用构造函数和原型对象来创建对象 构造函数 构造函数是用new创建对象时调用的函数,与普通唯一的区别是构造函数名应该首字母大写 function Person(){ this.age = 30; } var person1 = new Person(); console.log(person1.age);//30 根据需要,构造函数可以接受参数 function

js(面向对象,继承与原型对象)

一.定义: 程序用来描述的生活中的具体事务(对象:是封装一个事物属性与功能的程序结构):主要是用于大程序的维护 二.创建面向对象 1.自定义对象直接量(创建对象) 语法:var obj = { 属性名:属性值, ....:...., 方法名:function(){..this.属性名..}, ... } 举例:var lilei={ sname:"Li Lei", sAge:12, intr:function (){ console.log("I'm "+this.

JavaScript中的面向对象编程,详解原型对象及prototype,constructor,proto,内含面向对象编程详细案例(烟花案例)

面向对象编程: 面向:以什么为主,基于什么模式 对象:由键值对组成,可以用来描述事物,存储数据的一种数据格式 编程:使用代码解决需求 面向过程编程: 按照我们分析好的步骤,按步骤解决问题 优点:性能比面向对象高,适合跟硬件联系很紧密的东西 缺点:没有面向对象那么容易维护,复用,扩展 面向对象编程: 把事务分解成一个个对象,然后由对象之间分工与合作,分工明确,每一个对象都是功能中心 面向对象特性:封装性.继承性 .多态性 封装性:将一个功能封装起来,小封装 将多个函数封装起来,整体封装起来形成一个

ECMAScript面向对象——之原型对象

原型对象 1.每只要创建一个新的函数,就会根据默认的规则创建一个prototype属性,这个属性指向函数的原型对象. 2.原型对象有一个constructor构造函数属性,又指回它所在的函数 3.如果函数是构造函数,那么由这个函数创建的实例有一个内在的指针[不可操作]也指向该函数的原型对象 关系图如下: 上图中实例的[[prototype]]是不能直接通过代码访问的.所以要判断某个原型对象是不是某个实例的原型的时候, 可以通过以下两种方式来判定: 1.Person.prototype.isPro

Javascript 面向对象一:封装数据个方法,从原型对象生成实例

一. 生成对象的原始模式 假定我们把猫看成一个对象,它有"名字"和"颜色"两个属性. var Cat = { name : '', color : '' } 现在,我们需要根据这个原型对象的规格(schema),生成两个实例对象. var cat1 = {}; // 创建一个空对象 cat1.name = "大毛"; // 按照原型对象的属性赋值 cat1.color = "黄色"; var cat2 = {}; cat2.n

面向对象中构造函数,原型对象和实例的关系图

总结 以下代码为例 function Person(){} Person.prototype.c=function(){} var p1=new Person(); var p2=new Person(); 1.构造函数有一个prototype属性,(任何函数都有这个属性)这个属性表示原型对象 Person.prototype 2.构造函数的原型对象有个consturctor属性,指向构造函数本身 Person.prototype.constructor===Person 3.构造函数的原型对象