构造函数,原型对象,实例对象

一、构造函数,原型对象,实例对象

1.1 基本概念

1、对象:

  • 属性和方法的集合,即变量和函数的封装。
  • 调用构造函数产生的实例对象, 每个对象都有一个__proto__属性,指向这个对象的构造函数的原型对象

2、构造器函数:

  • 用于创建对象的函数,通过new关键字生成对象。
  • 函数名一般首字母大写的。
  • 每创建一个函数, 该函数都会自动带有一个prototype属性。该属性是一个指针,指向一个对象,该对象称之为原型对象(后期我们可以使用这个原型对象帮助我们在js中实现继承)

3、原型对象:

  • 默认有一个属性constructor,该属性也是一个指针,指向其相关联的构造函数
  • 原型对象其实就是普通对象(但 Function.prototype 除外,它是函数对象,但它很特殊,它没有prototype属性(前面说到函数对象都有prototype属性))
function Person(){};
console.log(Person.prototype) //Person{}

console.log(typeof Person.prototype) //Object
console.log(typeof Function.prototype) // Function,这个特殊
console.log(typeof Object.prototype) // Object
console.log(typeof Function.prototype.prototype) //undefined

1.2 总结

三者的关系是

  • 每个构造函数都有一个指向原型对象的指针,
  • 原型对象上包含着一个指向构造函数的指针,
  • 而实例都包含着一个指向原型对象的内部指针

1.3 举例

function People(){
    this.type='人'
}
People.prototype.showType=function(){
    alert(this.type);
}

var person=new People();
//调用原型对象上面的方法
person.showType();//最后结果弹框弹出人
  • 构造函数People(), People.prototype指向原型对象,其自带属性construtor又指回了People,即People.prototype.constructor==People.
  • 实例对象person由于其内部指针__proto__指向了原型对象,所以可以访问原型对象上的showType方法。

person1.__proto__ == Person.prototype

Person.prototype.constructor = Person

person1.constructor == Person

二 原型链

举例1

在第一部分我们说到,所有的实例都有一个内部指针指向他的原型对象,并且可以访问到原型对象上的所有属性和方法。

  • person实例对象的__proto__属性,指向了People的prototype属性,即原型对象,可以访问People原型对象上的所有属性和方法
  • 如果People原型对象变成了某一个类的实例aaa,这个实例又会指向一个新的原型对象AAA,那么person此时能访问aaa的实例属性和AAA原型对象上的所有属性和方法了。
  • 同理新的原型对象AAA碰巧又是另外一个对象的实例bbb,这个对象实例指向原型对象BBB,那么person就能访问bbb的实例属性和BBB原型上的属性和方法了。

举例2

function People(){
    this.type='人'
}
People.prototype.showType=function(){
    alert(this.type);
}

function Woman(){
    this.sex='女';
    this.age=34;
}
Woman.prototype = new People();

var w=new Woman();
console.log('大家好,我的种类是:'+w.type+",我的年龄是:"+w.age+",我的性别是:"+w.sex);
//输出结果:
//大家好,我的种类是:人,我的年龄是:34,我的性格是:女
//w.type是People上面定义的type

解释一下以上代码.

首先先定义了People构造函数,通过new People()得到实例,会包含一个实例对象type和一个原型属性showType。

另外定义一个Woman构造函数,然后情况发生变化,本来构造函数Woman的prototype会执行Woman的原型对象,但是我们这里稍有改变,将Woman构造函数的prototype指向了People实例对象覆盖了Woman的原型对象。

当Woman的实例对象woman去访问type属性时,js首先在woman实例属性中查找,发现没有定义,接着去Woman的原型对象上找,woman的原型对象这里已经被我们改成了People实例,那就是去People实例上去找。先找People的实例属性,发现没有type,最后去People的原型对象上去找,终于找到了。这个查找就是这么一级一级的往上查找。

举例3

function People(){
    this.type='人'
}
People.prototype.showType=function(){
    alert(this.type);
}
function Woman(){
    this.sex='女';
    this.age=34;
    this.type='女生';//如果这里定义了type属性,就不会层级查找,最后在People找到该属性
}
Woman.prototype=new People();
var w=new Woman();
console.log('大家好,我的种类是:'+w.type+",我的年龄是:"+w.age+",我的性别是:"+w.sex);
//输出结果:
//大家好,我的种类是:女生,我的年龄是:34,我的性格是:女

这就说明,我们可以通过原型链的方式,实现 Woman继承 People 的所有属性和方法。

总结
就是当重写了Woman.prototype指向的原型对象后,实例的内部指针也发生了改变,指向了新的原型对象,然后就能实现类与类之间的继承了

练习

练习1

构造函数Person 实例对象person1

// 题目
1 : person1.__proto__ 是什么?
2 : Person.__proto__ 是什么?
3 : Person.prototype.__proto__ 是什么?
4 : Object.__proto__ 是什么?
5 : Object.prototype.__proto__ 是什么?

// 答案
1 : person1.__proto__ === Person.prototype (person1的构造函数Person)

2 : Person.__proto__ === Function.prototpye (Person的构造函数Function)

3 : Person.prototype.__proto__  === Object.prototype (Person.protyotype是一个普通对象,因为一个普通对象的构造函数都是Object)

4 : Object.__proto__ === Function.prototpye (Object的构造函数Function)

5 : Object.prototype.__proto__ === null (Object.prototype 也有__proto__属性,但是它比较特殊,是null,null处于原型链的顶端。)

原型链的形成是真正是靠__proto__ 而非prototype

练习2

var FunctionExample = function () {}

Object.prototype.a = function() {}

Function.prototype.b = function() {}

var f = new FunctionExample();

这时候f能否访问到a和b ??
// 所有普通对象都源于这个Object.prototype对象,只要是对象,都能通过原型链访问到a

f.__proto__ === FunctionExample.prototype;

FunctionExample.prototype.__proto__ === Object.prototype;
// 取b我们可通过 f.constructor.b就能访问到b,因为 f.constructor == FunctionExample

f.constructor === FunctionExample;

FunctionExample.__proto__ === Function.prototype;
console.log(f) // FunctionExample {}
console.log(f.constructor)  // [Function: FunctionExample]
console.log(FunctionExample.prototype) // FunctionExample {}, 其实可以理解成FunctionExample.prototype就是一个实例
console.log(FunctionExample.prototype.constructor) // [Function: FunctionExample]
console.log(f.__proto__) // FunctionExample {} , 可以这么理解,实例的proto指向它的构造函数的原型对象,也就是f.__proto__ == FunctionExample.prototype
console.log(f.constructor.b) // Function,因为f.constructor指向 FunctionExample, 而 FunctionExample.prototype相当是Function的一个实例,所以在Function.prototype上有个b函数,FunctionExample照样可以访问的到
console.log(f.constructor.prototype.__proto__); // { a: [Function] } 可以访问到a函数,因为f.constructor.prototype其实就是等于FunctionExample {},而每个对象都有个__proto__属性,Function.prototype.__proto__ == Object.prototype,所以也能访问到a方法

练习3

function SuperType() {
  this.colors = ['red', 'yellow']
}

function SubType() {

}
// 继承了SuperType
SubType.prototype = new SuperType();

var instance1 = new SubType() // intance.constructor = SuperType
instance1.colors.push('black')
console.log(instance1.colors) // ['red', 'yellow', 'black']

var instance2 = new SubType()
console.log(instance2.colors) // ['red', 'yellow', 'black']

理解一下原型和原型链

// 为什么instance1.constructor = SuperType ?
// 为什么 SubType.prototype.constructor = SuperType ?

console.log(instance1.constructor) // SuperType
console.log(SubType.prototype.constructor) // SuperType

console.log(instance1.__proto__ == SubType.prototype) // true
console.log(SubType.prototype.__proto__ == SuperType.prototype) // true

console.log(SubType.__proto__ == SuperType.prototype) // false
console.log(SubType.__proto__ == Function.prototype) // true

console.log(SuperType.prototype.constructor == SuperType) // true
console.log(SuperType.__proto__ == Function.prototype) // true
console.log(SuperType.prototype.__proto__ == Object.prototype) // true

练习4

function SuperType() {
  this.colors = ['red', 'yellow']
}

function SubType() {
  // 继承了SuperType
  SuperType.call(this);
}

var instance1 = new SubType()
instance1.colors.push('black')
console.log(instance1.colors) // ['red', 'yellow', 'black']

var instance2 = new SubType()
console.log(instance2.colors) // ['red', 'yellow']

思考一哈?

console.log(instance1.constructor) // SubType
console.log(SubType.prototype.constructor) // SubType
console.log(SubType.prototype.__proto__) // {}

console.log(instance1.__proto__ == SubType.prototype) // true
console.log(SubType.prototype.__proto__ == SuperType.prototype) // false
console.log(SubType.prototype.__proto__ == Object.prototype) // true

console.log(SubType.__proto__ == SuperType.prototype) // false
console.log(SubType.__proto__ == Function.prototype) // true

console.log(SuperType.prototype.constructor == SuperType) // true
console.log(SuperType.__proto__ == Function.prototype) // true
console.log(SuperType.prototype.__proto__ == Object.prototype) // true

原文地址:https://www.cnblogs.com/qiqi715/p/10431095.html

时间: 2024-11-07 01:28:27

构造函数,原型对象,实例对象的相关文章

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

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

Python高级语法-对象实例对象属性-类与实例,class方法静态方法等(4.6.1)

目录 1.说明 2.代码 关于作者 @ 1.说明 python中属性:类属性,实例属性 方法:类方法,实例方法,静态方法 想修改类属性,只能是类方法,因为只有类方法把cls(类)传入数据里面 静态方法也就是个普通的方法,为了方便而已 实例方法,不能通过类来直接调用,要调用也可以self = 对象名 具体下面 2.代码 class Provice(object): #类属性 country = "china" def __init__(self,name): #实例属性 self.nam

实例对象、构造函数、原型之间的关系

实例对象.构造函数和原型之间的关系 实例对象 实例对象中只有__proto__属性,所有的实例都指向自己构造函数的原型.__proto__属性里面有构造器construction和__proto__. 构造器指向原型所属的构造函数,__proto__属性指向Object的原型. 实例对象里面有一个特例: 这个是一个特例,里面有prototype和__proto__俩个属性,__proto__指向Function的原型,prototype是一个单纯的对象,是一个Object的实例,相当于{},就是

JS面向对象篇二、什么是原型?原型对象与实例对象、构造函数的关系及相关方法

本文内容: 1.构造函数.原型对象与实例对象之间的关系: 2.isPrototypeOf()和Object.getPrototypeOf(); 3.实例对象上与原型对象上同名的属性处理: 4.hasOwnProperty()方法和in操作符判断属性来自实例对象本身还是它的原型对象: 5.for-in.Object.keys()和Object.getOwnPropertyNames()方法获取实例对象或者原型对象上的属性: 6.需注意的特殊问题 构造函数.原型对象与实例对象 function Pe

如何确定 原型与实例之间的关系

instanceof  可以用来确定实例与原型之间是否存在关系 只有当原型与实例有关系的时候 才能依赖于 instanceof 确定 function SpecialArray(){ //创建数组 var values = new Array(); //添加值 values.push.apply(values, arguments); //添加方法 values.toPipedString = function(){ return this.join("|"); }; //返回数组 r

对象(一)--对象的继承

聊一聊JavaScript中的对象的继承 吐槽 时间过得是真的快,感觉才更新博客怎么就快一个礼拜了...这两天看了点python和flask框架了解了下,最后还是打算去系统地学习下node,又看了MongoDB,之后觉得Linux挺有意思的又去找资料学习(选发行版本,装虚拟机...), 感觉把时间都折腾在这儿了,有点不务正业(想了想还是日后抽时间学习吧,现在还是把前端知识巩固好,毕竟目前是个连实习都找不到的渣渣... 不过node还是要学的,计划之后手撸一个个人博客练练手... 前言 在前一篇对

面向对象之构造函数、实例对象、原型

一.面向对象首先有一个需求,点击按钮改变div的样式.按照常规的思维来写,我们可能是先获取到目标元素,然后给目标元素添加事件,在事件中书写div需要改变的样式属性.如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script type="text

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

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

构造函数、原型对象及其实例对象

构造函数有个 prototype 属性指向原型对象 实例化的对象有一个 [[prototype]] 属性指向原型对象 原型对象有一个 constructor 属性指向构造函数. 如果在实例的对象覆盖了原型对象中的某个属性或者方法后,会切断这个属性或方法指向原型的连接.即便后面把这个属性或者方法设置为 null,也不会恢复这个连接.只有通过 delete 操作符可以完全删除.注意:设置属性为 null 后调用这个属性,显示的是 null,设置方法为 null 后调用这个方法,显示的是 object