关于对象、构造函数、原型、原型链、继承

对象:

在传统的面向过程的程序设计中,会造成函数或变量的冗余。而js中对象的目的是将所有的具有相同属性或行为的代码整合到一起,形成一个集合,这样就会方便管理,例如:

var person1={
    name:"memphis",
    age:26,
    showMessage:function(){
        alert("name:"+this.name);
    }
};
person1.showMessage();//输出name:memphis

以上的例子将name、age、showMessage放进person这个对象中,方便管理也减少命名困难。

1)、内存会给每个对象分配一个内存空间;

2)、函数也是一个对象

每一个对象都会占据一定的内存空间。

构造函数:

对象的产生方便了代码的管理,但是又产生了一个问题,如果又定义了一个对象person2,如下:

var person2={
    name:"memphis",
    age:26,
    showMessage:function(){
        alert("name:"+this.name);
    }
};

这样的话person2和person1就产生了代码重复问题(person1和person2有同样的属性和行为);由此就引出了构造函数的概念。

function Person(name,age)={
    this.name=name;
    this.age=age;
    this.showMessage=function(){
       alert("name:"+this.name);
    };
}
var person1=new Person(tan,26);
var person2=new Person(song,16);

这样通过构造函数我们就不用反复去重新定义属性和行为,我们就创造了两个对象person1和person2person1和person2也叫作构造函数Person的两个实例。

构造函数:用来在创建对象时初始化对象。特点:构造函数名一般为大写字母开头;与new运算符一起使用来实例化对象。

function Person(){}         //Person构造函数
var p=new Person();         //Person构造函数创建对象,也可叫做实例化

原型:

构造函数可以解决代码管理和重复性的问题。但是,正如在 对象 中提到的函数也是对象,也会有一定的内存空间,属性可以每个对象占据一个空间,但是方法也就是行为,他对每个对象来说动作是一样的,只是可能传的参数不一样。因此要想一个方法来解决内存空间被过多的占用的问题。

拟解决方法1:函数的定义转移到构造函数外,例如:

function Person(name,age)={
    this.name=name;
    this.age=age;
    this.showMessage=showMessage;
}
function showMessage(){
    alert("name:"+name);
}

这时构造函数中this.showMessage会指向showMessage这个全局变量,先在构造函数的内部去找showMessage这个变量,然后去外部找。

这个解决方法看似可以,但一个对象若有多个方法时,代码的封装性无法体现,而且全局的函数只是为一个对象服务,全局性体现的不明显。

拟解决方法2:原型

每个函数在创建的时候都会默认的分配一个prototype属性,构造函数也不例外。

那么prototype属性是什么?

=> prototype是一个指针,它指向一个对象。指针就像是:

想要把一本书存在一间房子里(行为),要完成这个行为,就要先建房子然后把书放进房子,下次要存一本新书,就还要先建房子再放另一本书,这就很麻烦了。

更好的解决办法:

整个行为中,房子是一个确定的动作,不需要每次都重建,建一次房子把地址记下来,以后每一次有放书这个动作时只需要通过地址找到对应的房子就行了。

如上面的例子:

showMessage就是建房子的动作,name是书,prototype属性是地址。构造函数就是每放一本书就要建一个房子,而原型就是通过地址找房子。

//建房子
function Person(){
}
//房子里有什么并确定了指针的指向
Person.prototype={
    name:"memphis",
    age:"22",
    showMessage:function(){
       alert("name:"+this.name);
    }
};
var person1 = new Person();

person1这样就有了指针,就能访问指针指定的内存空间。

1)、person1中也可以有自己属性,而且对于person1和原型Person中都有的属性,优先考虑的是person1中的属性。

2)、不能通过person1改变原型属性值,实例person1只是获取了一个指向原型的指针,并没有改变原型的权利。(注意:对于包含引用类型的属性——例如数组。有一些操作是允许通过地址去访问内存的,例如push,这些操作就有可能改变原型属性,这个改变会造成灾难性的后果,因为所有引用这个原型的对象都会随之改变。)

原型链:

没有原型的对象为数不多,Object.prototype算一个,它不继承任何属性。其他原型对象都是普通对象,普通对象都具有原型。Object.prototype是祖宗,其他的构造函数都是它儿子或者孙子、重孙子。它的孙子的原型是他儿子,同样也是它,因为他儿子是继承它的,这样一来,每个对象都继承至少一个原型对象,这一系列链接的原型对象就是所谓的“原型链”。

每一个对象都有自己的原型对象,原型对象本身也是对象,原型对象也有自己的原型对象,这样就形成了一个链式结构,叫做原型链。

上面说的都是同类型下的对象,person1和person2都是Person的实例。如果有Person和Man两个引用类型。Person中的属性和方法是有Man需要的,想直接从Person中所有的属性和方法拿过来,这就是继承。

作为一个继承的引用类型,能获取谁的属性和方法,name在这个问题上就会有原型链的概念。当对象尝试获某个属性时,该对象没有,会尝试从原型对象中去找,原型对象没有,在从原型对象的原型去找,最后到达Object.prototype。

例如:
function Person(name,age){
this.pname=name;
this.page=age;
}
Person.prototype={
showPMessage:function(){
alert("name:"+this.pname);
}
};
function Man(name,age){
    this.mname=name;
this.mage=age;
}
// 这一句话表示原型的指针指向了Person
Man.prototype = new Person("memphis",22,"man");
//  给原型添加方法一定要放在替换原型的语句之后
Man.prototype.test="wo shi";
Man.prototype.showMMessage=function(){
alert("name:"+this.mname);
};
var song=new Man("song",1);
song.showMMessage();//显示song
song.showPMessage();//显示memphis

继承

1. for-in继承

function Person(){              //父类
     this.name="水煮鱼";
     this.age=18;
}
function Son(){                 //子类
}
var p=new Person();
var s=new Son();
for(var k in p){
    s[k]=p[k];
}
console.log(s.name);           //水煮鱼
console.log(s.age);            //18

2. 原型继承

function Human(){
    this.name="香辣虾";
    this.age=21;
}
function Man(){
}
Man.prototype=new Human();
var m=new Man();
console.log(m.name);           //香辣虾
console.log(m.age);            //21  

3. 经典继承

var animal={
    name:"阿咪",
    type:"猫科"
};
var a=Object.create(animal)    //ES5属性
console.log(a.name);           //阿咪
console.log(a.type);           //猫科

Object.create()是让一个对象的原型继承另外一个对象;所以虽然a.name和a.age是可以访问成功的,但实际上a本身并没有这些属性,而是a的原型上有这些属性。

如下图所示:

时间: 2024-12-09 18:32:33

关于对象、构造函数、原型、原型链、继承的相关文章

对象构造函数的原型图

对象的定义其实很广泛,万物皆为对象,我们创建对象一般都是用构造函数来创建的,这里我们来说说构造函数创建对象的原型图把. 这个问题有点抽象,举个例子来说,方便一点: 这是我们构造函数,这里我们要结合一张 图来说明就更清楚了,这里我们就用一个实例p1好了,其他两个就不用了. 这是构造函数和实例的初始关系,person就是这个构造函数,它里面其实有个属性叫prototype,prototype属性的值也是个对象,而这个对象其实就是称作构造函数的原型对象.到这里那上面那张图里应该要多谢东西了: 这个原型

MDN——javascript——入门——第三章对象——对象.构造函数.原型链.继承——知识点总结

对象Object 由属性property(变量).方法method(函数)组成 var objectName = { member1Name : member1Value, member2Name : member2Value, member3Name : member3Value } member(成员)的值是任意的, 一个如上所示的对象被称之为对象的字面量(literal)——手动的写出对象的内容来创建一个对象.不同于从类实例化一个对象,我们会在后面学习这种方式. 访问对象成员 1.点表示法

原型,原型对象,原型链,构造函数,继承(一)

前言:javascript中 万物皆对象 , 但是对象是有区别的 分为普通对象(object)和函数对象(function): ①由以下三种形式创建的对象为函数对象: function fun1(){} var fun2 = function(){} var fun3 = new Function(); console.log(typeof fun1);//function console.log(typeof fun2);//function console.log(typeof fun3);

js最好的继承机制:用对象冒充继承构造函数的属性,用原型链继承 prototype 对象的方法。

js最好的继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法. function ClassA(sColor) { this.color = sColor; } ClassA.prototype.sayColor = function () { alert(this.color); }; function ClassB(sColor, sName) {//在 ClassB 构造函数中,用对象冒充继承 ClassA 类的 sColor 属性 ClassA.call(th

Js中的对象、构造函数、原型、原型链及继承

1.对象 在传统的面向过程的程序设计中,会造成函数或变量的冗余.而JS中对象的目的是将所有的具有相同属性或行为的代码整合到一起,形成一个集合,这样就会方便我们管理,例如: var person1={    name:"tan",    age:26,    showMessage:function(){        alert("name:"+this.name);    }};person.showMessage();//输出name:tan 以上的例子将nam

原型、原型对象的理解 及其原型链继承

在 ES5 中,有的人可能对原型,原型对象,及其原型链不是很清楚,今天我就说说对这些的深入认识下.(如果有什么不懂得欢迎留言探讨,当然如果有什么写的不恰当的也希望大家留言备注.) 首先,再说原型与原型对象之前,当然有必要清楚构造函数,实例,原型与原型对象之间的关系.其实他们的关系也很简单. 构造函数,实例,原型与原型对象之间的关系: 构造函数有它自己的属性及其方法,其中包括自己定义的属性和方法外,还有两个特殊属性(prototype.constructor):而每个他的实例都会拥有它的所有属性和

一步步学习javascript基础篇(5):面向对象设计之对象继承(原型链继承)

上一篇介绍了对象创建的几种基本方式,今天我们看分析下对象的继承. 一.原型链继承 1.通过设置prototype指向“父类”的实例来实现继承. function Obj1() { this.name1 = "张三"; } function Obj2() { } Obj2.prototype = new Obj1(); var t2 = new Obj2(); alert(t2.name1); 这里有个明显的缺点就是:(如果父类的属性是引用类型,那么我们在对象实例修改属性的时候会把原型中

原型、原型对象、构造函数、原型链理解

1. 基本概念: "原型属性"也可以叫做"原型"(prototype):所有函数都有prototype,我觉得可以理解为python中的类属性,不需要通过实例,直接用类(es5就是函数名)可以调用,下面列举了三种创建函数的方法,函数创建后都有prototype属性,prototype指向"原型对象". // 函数声明 function F1() { }; // 表达式定义 let F2 = function () { }; // 函数构造 let

对象冒充实现继承,原型链继承方法,以及组合继承模式

function Person (){ this.name=“张三”; this.run = function(){ alert( this.name+'在运动' ) } } Person.prototype.work = function(){ alert( this.name+'在工作’ ) } // web类 继承person类 原型链+对象冒充的组合继承模式 function web(){ Person.call( this )  //  对象冒充实现继承 } var w = new w