建立对象(一):建立与继续

建立对象

一.建立对象的要领

明白原型对象:

不管什么时候,只需建立了新函数,就会依据一组特定的规则为该函数建立一个 prototype属性,这个属性指向函数的原型对象。在默许状况下,一切原型对象都邑自动取得一个constructor属性,这个属性包含一个指向prototype属性的地点函数的指针。(重写原型属性会默许作废constructor属性)细致可见文章下图。

建立object实例的体式格局有三种:对象字面量示意法、new操纵符跟object组织函数、(ECMAScrript5中的)object.create()函数。下面重要讲的是最为庞杂的new操纵符跟object组织函数的建立对象实例的要领。

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("NIcho",29,"software engineer");

工场形式的题目:

工场形式虽然处理了建立多个类似对象的题目,然则没有处理对象辨认的的题目(即如何晓得一个对象的范例)。

1.2.组织函数形式
运用:建立对象的自有属性的重要要领,每定义一个函数就实例化了一个对象.
function Person(name,age,job){

    this.name=name;
    this.age=age;
    this.job=job;
    this.sayName=function(){
        alert(this.name);

}

//将组织的函数Person实例化,传入的参数作为自有属性,而且继承自Person.prototype
var person1=new Person(NIcho",29,"software engineer);
var person2=new Person(Jhon",26,"software engineer);

注重:1.alert(Person.name);//undefined
Person函数替代了createPerson函数,另有以下差别之处:
(1)没有显式建立对象
(2)直接将属性和要领赋给this对象(这里的this指的就是这个组织的函数)
(3)没有return 语句
我们在这个例子中建立的对象既是object的实例又是person的实例(一切对象均继承自object。object能够明白为对象的根原型,我们所用到的一切对象要领的操纵,如toString 、substring 、splice等都是继承自object)

alert(person1 instanceOf Object);//true
alert(person1 instanceOf Person);//true

组织函数形式的题目:

运用组织函数的重要题目是,每一个要领都要在每一个实例上建立一次。person1和person2都有一个sayName的要领,但两个要领不是同一个Function实例(ECMAScript中的函数是对象,每定义一个函数就是实例化了一个对象)。

假如没有自定义向person原型中增加属性,实例化今后则获得Person自有属性的一个副本,而且继承object。(注:person1与person2中sayName()援用位置差别)
《建立对象(一):建立与继续》

                         图1组织函数形式下的实例化对象

经由过程把函数定义转移到组织函数外来处理:

//全局函数
function sayName(){
    alert(this.name);
}

对应的:this.syName:sayName;

1.3原型形式
运用:用于定义实例同享的属性和要领

function Person(){
}
Person.prototype.name="Nicho";
Person.prototype.age=29;
Person.prototype.jod="software engineer";
Person.prototype.sayName=function(){alert(this.name)};
var person1=new Person();
person1.sayName();//"Nicho" 继承Person.prototype
var person2=new Person();
person2.sayName();//"Nicho"继承Person.prototype
alert(person1.sayName==person2.sayName);//true 援用位置雷同

《建立对象(一):建立与继续》

                            图2 person1、person2继承自person.prototype

(注:继承衔接存在与实例与组织函数的原型之间而不是实例与组织函数之间)

关于原型上的一些函数:

1.检测obj是不是为obj1的原型:obj.isPrototypeOf(obj1)//返回true/false
2.取得obj1的原型:object.getPrototypeOf(obj1)
3.检测一个属性是不是存在于实例中(也就是自有属性)照样原型中(来自于继承):
Obj1.hasOwnProperty();//假如obj1有自有属性则返回true,不然返回false

1.4组合运用组织函数形式和原型形式
组合运用组织函数形式和原型形式既能够继承原型对象的属性,又能够设置自在属性

function Person(name,age,job){
        this.name=name;
        this.age=age;
        this.job=job;
}
Person.prototype={
    constructor:Person,
    sayName:function(){
        alert("Hi");
    }
   }
var person1=new Person(“Nicho”,29,”software engineer”);
//person1自有属性:name aga job;原型属性(来自继承):constructor sayName

代码读取某个对象的某个属性时的搜刮要领:

搜刮首先从对象实例最先,假如实例中找到了给定名字的属性,则返回该属性的值。假如没有找到,则继承搜刮指针指向的原型对象,在原型对象中查找给定名字的属性。假如在原型对象中找到了该属性,则返回属性的值,不然一向向上查找给定名字的属性,直到object。假如没有找到则返回undefined。

这就须要我们注重:虽然我们能够经由过程对象实例接见原型中的值,但却不能经由过程对象实例(注重!!这里说的是经由过程对象实例而不是在原型中修正属性)来重写原型中的值。假如在实例中增加了一个与实例原型中同名的属性,该属性将会屏障原型中的谁人属性。来看下面的的例子:

function Person(){

}
Person.prototype.name="Nicho";
Person.prototype.age=29;
Person.prototype.jod="software engineer";
Person.prototype.sayName=function(){alert(this.name)};
var person1=new Person();
var person2=new Person();
 person1.name="Greg";
alert(person1.name);//Greg-来自实例
alert(person2.name);//Nicho-来自原型;
//person1对属性 name的修正并不能修正原型上的响应属性,因而person2继承自原型

《建立对象(一):建立与继续》

1.person1=new Person()与 person3=person1是差别的:前者是实例化一个对象,
后者遵照复制函数(对象援用)的道理
2.对对象团体举行操纵(援用)和对对象中的某个属性(值)举行操纵完成道理是差别的
1). 全部对象的复制即援用雷同

var person3=person1;//全部对象的复制即援用雷同(指针指针指针!只是一个索引,现实存储都不在指针位置下)
person3.name=”newName”;//修正属性称号的值
alert(person1.name);//newName;//另一个来自此处的援用属性的值会修正;即复制对象道理
alert(person1.isPrototypeOf(person3));//false
alert(Person.prototype.isPrototypeOf(person3));//true

2).简朴的属性的复制,并不是援用同一个属性值.

var person1=new Person("NIcho",29,"software engineer");
  var person2=new Person("HIcho",9,"Hardware engineer");
  person1.name=person2.name;//简朴的属性的复制,并不是援用同一个属性值
  person2.name="NEW";//尝试赋新值
  alert(person1.name);//HIcho,申明是值的通报而并不是援用

二.继承

1.ECMAScript只支撑完成继承,而且完成继承重如果依托原型链来完成的。
2.其基本思想是应用原型让一个援用范例继承另一个援用范例的属性和要领。(即:原型链的构建是经由过程将一个范例的实例赋值给另一个组织函数的原型来完成的)

2.1原型链的继承

function superType(){
    this.property=true;
   }
    superType.prototype.getSuperValue=function(){
        return this.property;
    };
    function subType(){
        this.subProperty=false;
    }
    //继承superType
    subType.prototype=new superType();
    subType.prototype.getSubValue=function(){
        return this.subProperty;
    };
    var instance=new subType();
    alert((instance.getSuperValue)());//true  getSuperValue来自superType.prototype
    alert(instance.property);//true   property来自superType实例
    

完成的实质是重写原型对象,代之以一个新范例的实例。换句话说,本来存在于superType的实例的一切属性和要领(包含自有属性和继承属性),如今也存在于subType.prototype中了。
《建立对象(一):建立与继续》

                        图4 subType继承了superType 

(此时instance.constructor如今指向的是superType,由于subType的原型指向了另一个对象superType的原型,而这个原型对象的constructor指向的是superType)

注重:
1.别忘记默许的对象Object.prototype: subType继承了superType,superType继承了Object.prototype

  1. 肯定原型和实例的关联:

(1)instanceOf;测试实例与原型链中涌现过的组织函数

alert(instance instanceOf  superType);//true
alert(instance instanceOf  subType);//true

(2)isPrototypeOf:只需原型链中涌现过的原型都能够说是该原型链所派生出来的实例的原型

alert(superType.protoType.isPrototypeOf (instance));//true
alert(subType.protoType.isPrototypeOf (instance));//true

原型链的题目:
在经由过程原型来完成继承时,原型现实上会变成另一个范例的实例。因而,本来的实例属性也就水到渠成地变成了如今的原型属性了。

2.2处理原型链继承带来的题目的要领

处理这个题目的手艺是借用组织函数,运用最多的继承形式是组合继承。另外另有原型式继承,寄生式继承,寄生组合继承。这里重要讲借用组织函数和组合继承。

(1)借用组织函数
//在子范例组织函数的内部挪用超范例的组织函数

function superType(){
    this.colors=["red","blue","green"];
  }
  function subType(){
    //继承了superType
    superType.call(this);//在新建立的subType实例的环境下挪用superType函数
    //这样一来,就会在新subType对象上实行superType函数中定义的一切初始化代码
    //效果subType的每一个实例都邑具有本身的color属性的副本了
  }
  var instance1=new subType();
  instance1.colors.push("black");
  alert(instance1.colors);//red,blue,green,black
  var instance2=new subType();
  alert(instance2.colors);//red,blue,green

(2)组合继承
思绪是运用原型链完成对属性和要领的继承,而经由过程借用函数来完成对实例属性的继承

function superType(name){//超类中定义,为今后继承该实例属性(子类的原型)做准备
    this.name=name;
    this.colors=["red","blue","green"];
  }
superType.prptotype.sayName=function(){
alert(this.name);
}// superType.prptotype新增属性,位于继承的更高层
function subtype(name,age){//建立自有属性
superType.call(this,name); //继承属性式的建立
this.age=age;//直接新增
}
//继承要领
subtype.prototype=new superType();
subtype.prototype.constructor=subtype;
subtype.prototype.sayAge=function(){//subtype.prototype为本身新增要领
alert(this.age);
}
var instance1=new subType(“Nicho”,29);
  instance1.colors.push("black");
  alert(instance1.colors);//red,blue,green,black
instance1.sayName();//”Nicho”
instance1.sayAge();//29

  var instance2=new subType(“Greg”,27);
  alert(instance2.colors);//red,blue,green
instance2.sayName();//”Greg”
instance2.sayAge();//27

总结:
1.subType的自有属性: this.age=age

2.subType的继承属性:
(1)superType.prptotype.sayName 、subtype.prototype.sayAge
(2)function superType(name){

this.name=name;
        this.colors=["red","blue","green"];
          }

3.
下面让我们看下一种状况:重写原型对象(完整重写而不是简朴的增加原型对象的属性)
我们晓得,在挪用组织函数是会为实例增加一个prototype指针,而把这个原型修正为另一个对象就即是切断了组织函数与最初原型之间的联络。请记着:实例中的指针仅指向原型而不指向组织函数。

function Person(){};
var friend=new Person();
Person.prototype={
Constructor:Person,
Name:“Nicholas”,
Age:29,
sayName=function(){
alert(“this.name”);
}
}
friend.sayName();//error

重写原型对象之前:

《建立对象(一):建立与继续》

重写原型对象今后:

《建立对象(一):建立与继续》

由图可见:重写原型对象切断了现有原型与任何之前已存在的对象实例之间的联络,它们援用的还是最初的原型

    原文作者:specialCoder
    原文地址: https://segmentfault.com/a/1190000004862501
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞