一、构造函数,原型对象,实例对象
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