JavaScript面向对象的程序设计1(创建对象)

怎样创建一个对象呢???


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("Nicholas", 29, "Sofrware Engineer");
        var person2=createPerson("Grey", 27, "Doctor");

存在问题:虽然解决了创建多个对象的问题,但是我们怎么知道这个对象的类型呢???


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("nike",29,"software engineer");
        var person2=new Person("grey",34,"doctor");
        alert(person1 instanceof Object);
必须使用new操作符,经历四个步骤:
(1)创建一个新对象
(2)将构造函数的作用域赋给新对象(故this就指向这个对象)
(3)执行构造函数中的代码,为这个新对象添加属性
(4)返回新对象
//person1和person2分别保存着Person的一个不同实例,这两个对象都有一个constructor(构造函数)属性,该属性指向Person
//检测对象类型
alert(person1.constructor==Object);//true
alert(person1.constructor==Person);//true
//但还是推荐使用instanceof
alert(person1 instanceof Person);//true
alert(person1 instanceof Object);//true

注意:person1和person2之所以是Object的实例,是因为所有的对象均继承自Object

存在的问题:其中的每个方法都要在每个实例上重新创建一遍。完成同样的事却干了两遍,有必要吗

 function Person(name,age,job) {
            this.name=name;
            this.age=age;
            this.job=job;
            this.sayName=function(){
                alert(this.name);
            };
        }
 alert(person1.sayName==person2.sayName);//false!!!

虽然能这样解决:

  function Person(name,age,job) {
            this.name=name;
            this.age=age;
            this.job=job;
            this.sayName=sayName;//共享全局作用域中的sayName()
        }
        function() sayName{
                alert(this.name);
            }
        var person1=new Person("nike",29,"software engineer");
        var person2=new Person("grey",34,"doctor");
        alert(person1 instanceof Object);

一个全局函数却只被某个对象调用,这算什么全局。


3.原型模式

(1)每个函数有一个prototype(原型)属性,它是个指针,指向一个对象,而这个对象的用途是包含所有实例所共享的属性和方法

好处:让所有对象实例共享它所包含的属性和方法。也就是说不必在构造函数中定义对象实例的信息,而是将这些信息直接添加到原型对象中

function Person(){

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

(2)当代码读取某个属性时,都会执行一次搜索。首先在对象实例本身开始搜索,如果没有找到,则到原型对象继续搜索。

虽然可以通过对象实例访问保存在原型中的值,但不能通过对象实例重写原型中的值 。如果在实例中添加的属性和原型对象中的同名,那么该属性将会屏蔽在原型中的那个属性。

function Person(){
        }
        Person.prototype.name="Nicholas";
        Person.prototype.age="29";
        Person.prototype.job="Software Engineer";
        Person.prototype.sayName=function () {
            alert(this.name);
        };
        var person1=new Person();
        var person2=new Person();
        person1.name="Curry";
        alert(person1.name);//Curry--来自实例
        alert(person2.name);//Nicholas--来自原型
        delete (person1.name);//删除之后就能回复对原型name的连接,因此再调用就返回原型的值
        alert(person1,name);//Nicholas--来自原型
        //使用hasOwnProperty()方法可以检测一个属性存在于实例中还是存在于对象中
        alert(person1.hasOwnProperty("name"));//false
        person1.name="Curry";
        alert(person1.hasOwnProperty("name"));//true

(3)同时使用hasOwnProperty()和in操作符,就能确定某个属性是存在于原型中还是对象实例中,如下:

alert(person2.hasOwnProperty("name"));//false
alert("name" in person2);//true
//存在于原型

(4)更简单的原型语法

前边有点蛋疼,每添加一个属性和方法就敲一遍Person.prototype。不妨像下面这样:

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

但是此时constructor不再指向Person,如下

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

那么怎样解决呢,如下:

function Person(){
        }
        Person.prototype={
            constructor:Person;//注意这里
            name:"Nicholas",
            age:29,
            job:"Software Engineer",
            sayName:function () {
                alert(this.name);
            }
        };

但是这将导致constructor的属性[[Enumerable]]变为true,也就是可枚举,那怎么办呢,如下:

           enumerable:false,//修改回来
           value:Person
        });

(5)

原型对象存在的问题:就是它的共享属性。
原型中的属性被很多实例共享,这种共享对于函数而言是非常合适的。对于那些包含基本值的属性倒也说得过去,毕竟只要在原型中添加同名属性就能将其屏蔽。但是对于引用类型的属性来说呢?
看看下面,你还行单独使用原型模式吗?

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值