Javascript学习和整理札记--原型继承Part(7)

prototype  原型(任何一个函数都有相应的prototype)

Javascript是一个没有类的语言,严格上讲应该不是面向对象的,采用原型继承来代替类继承。体现原型的地方主要有:属性写入 和属性读取。

-->基于'__proto__'的原型链的三类对象(大部分浏览器支持_proto_属性,尽管他不是一个标准属性)

   --->原型对象:自带的(Array、Function、Object啥的)、自定义的;与原型相关的有__proto__ 属性(均指向 Object.prototype,Object.prototype本身指向的为null),*.prototype属性,独有属性constructor(独有属性指向对应的构造函数对象)

   --->构造函数对象:原生的(类似原型对象Array啥的对应的)、自定义的;与原型相关的有__proto__ 属性(均指向Function.prototype 这个原型对象)和prototype属性(指向对应的原型对象*.prototype)

    --->实例对象:通过new **()所得到的实例;与原型相关的只有__proto__ 属性,指向其对应的原型对象 *.prototype

两个只能:

       实例只能通过其对应的原型对象的 constructor 才能访问到对应的构造函数对象; 

       构造函数只能通过其对应的 prototype 来访问相应的原型对象。

!!!基于'_proto_'来查找原型对象时,'__proto__'属性会指向该实例对象所继承到的原型对象即*.prototype

//通过_proto_寻找原型链关系

function TestRole(role){  //构造函数TestRole的原型对象为Function.prototype
    this.role = role;
};

TestRole.prototype = {name:"2tong",age:23}; 
//TestRole.prototype的原型对象为Object.prototype
//因为构造函数的prototype指向原型对象的.prototype

var test = new TestRole("student"); 
//test的原型对象为TestRole.prototype
//Function.prototype的原型对象为Object.prototype,Object.prototype的原型对象为null

-->prototype与自定义类

以prototype的形式声明的一些信息,构造出的实例可以以原型继承的方式获取到;

因此,采取这样的方式,可以大大减少不必要的内存申请,例如:

function Test(a,b){
    this.a = a;
    this.b = b;
    this.c = 0;
}

Test.prototype.add = function(){
    this.c += this.b;
    this.c += this.b;
}

Test.prototype.showResult = function(){
    console.log("The result is "+this.c+" .");
}
//当new Test的时候,add和showResult并不会每次都分配内存,就可以减少不必要的内存申请了

自带构造函数的原型:

Array.prototype
//访问结果为[]

自定义构造函数的原型:

function Test(role){
this.role = role;
}

Test.prototype = {name:"2tong",age:23};
Test.prototype
//访问结果为Object{name:"2tong",age:23}

实例的原型:

function Test(role){
this.role = role;
}

Test.prototype = {name:"2tong",age:23};
var temp = new Test("student");
temp.__proto__
//访问结果为Object{name:"2tong",age:23}

-->new关键字与原型继承的关系

function Test(role){
this.role = role;
}

Test.prototype = {name:"2tong",age:23};
var temp = new Test("student"); 
/**
new 的工作流程:
1:首先,会分配一个新的对象
2:设置新对象的相关属性、方法
   此处为以引用的方式继承Test.prototype上的各类属性、方法,继承的属性为实例对象的继承属性
   这种以引用方式进行继承的方式也可以称之为代理,代理的含义就是Test.prototype上的各类属性、方法变化时,实例的相关属性、方法会变化,而反之不可以
3:这个新对象作为构造函数的上下文,即this引用指向这个新对象,执行构造函数,类似于Test.apply(temp*,["student"]),设置实例对象的自有属性role
4:返回这个对象到执行new Test("student")的位置,赋值给前面的变量名,即temp
*/
temp.__proto__
//访问结果为Object{name:"2tong",age:23}

console.log(temp.role); 
//为temp的自有属性,可以根据更改进行变化

console.log(temp.name);
//为temp的继承属性,不可以根据temp的更改进行变化,尝试更改的时候,会出现temp的私有属性name
console.log(temp.age);
//为temp的继承属性,不可以根据temp的更改进行变化,尝试更改的时候,会出现temp的私有属性age

-->原型继承,铛铛铛

Javascript对象拥有自有属性和继承属性两种类型的属性,自有属性例如temp.role,通过构造函数的this.role = role;获取的属性,继承属性例如temp.name,代理Test.prototype获取的属性。

function Test(role){
this.role = role;
}

Test.prototype = {name:"2tong",age:23};
var temp = new Test("student"); 

console.log(temp.role); 
//为temp的自有属性,可以根据更改进行变化

console.log(temp.name);
//为temp的继承属性,不可以根据temp的更改进行变化,尝试更改的时候,会出现temp的私有属性name
console.log(temp.age);
//为temp的继承属性,不可以根据temp的更改进行变化,尝试更改的时候,会出现temp的私有属性age

        --->查询(启用原型链)

        在查询一个对象是否拥有一个属性A的时候,会先检查这个对象的自有属性是否具有这个属性A,如果没有的话,则检查这个对象的继承属性中是否具有这个属性A,如果没有的话,则判定没有了,返回undefined。

        --->赋值(不启用原型链,只看自有属性)

        在给一个对象的一个属性A赋值的时候,会先检测这个对象的自由属性是否具有这个属性A,如果有的话,就直接更改这个属性A的值,如果没有的话,会为这个对象创建一个自有属性A,并进行赋值,无论继承属性中是否有属性A。

function Test(role){
    this.role = role;
    this.sign = function(){
        console.log("u have been a member of "+this.role+"s.");
    };
 }

Test.prototype = {name:"2tong",age:23};
var temp = new Test("student"); 

console.log('name' in temp); //返回true 可以使用in来判断是否具有这个属性
console.log(temp.hasOwnProperty('name')); //返回false 可以使用hasOwnProperty()来判断是否具有这个自有属性
console.log(temp); //返回的为Test{role:"student",name:"2tong",age:23,sign:function}

temp.name = "tong";

console.log('name' in temp); //返回true
console.log(temp.hasOwnProperty('name')); //返回false 
console.log(temp); //返回的为Test{role:"student",name:"tong",age:23,sign:function} 因为访问的时候会先访问自有属性,所以会是tong而不是2tong

-->练习题目

function SuperTest(data) {
    var hello = function() { return "hello"; };
    hello.__proto__ = data;
    return hello;
}

var data = { name:"2tong", age: 23};
var test = SuperTest(data);

console.log(test());			//hello
console.log(test.name);		//2tong
console.log(typeof test); 	//function


猜你喜欢

转载自blog.csdn.net/orange_612/article/details/80180603
今日推荐