1、对象:
__proto__属性
,指向这个对象的构造函数的原型对象
。2、构造器函数:
prototype属性
。该属性是一个指针
,指向一个对象
,该对象称之为原型对象
(后期我们可以使用这个原型对象帮助我们在js中实现继承)3、原型对象:
属性constructor
,该属性也是一个指针
,指向其相关联的构造函数
。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
三者的关系是
function People(){
this.type='人'
}
People.prototype.showType=function(){
alert(this.type);
}
var person=new People();
//调用原型对象上面的方法
person.showType();//最后结果弹框弹出人
People.prototype
指向原型对象,其自带属性construtor又指回了People,即People.prototype.constructor==People
.person1.__proto__ == Person.prototype
Person.prototype.constructor = Person
person1.constructor == Person
在第一部分我们说到,所有的实例都有一个内部指针指向他的原型对象,并且可以访问到原型对象上的所有属性和方法。
People原型对象上的所有属性和方法
。如果People原型对象变成了某一个类的实例aaa
,这个实例又会指向一个新的原型对象AAA,那么person此时能访问aaa的实例属性和AAA原型对象上的所有属性和方法
了。person就能访问bbb的实例属性和BBB原型上的属性和方法
了。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的原型对象
上去找,终于找到了。这个查找就是这么一级一级的往上查找。
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指向的原型对象
后,实例的内部指针
也发生了改变,指向了新的原型对象,然后就能实现类与类之间的继承了
。
构造函数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
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方法
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
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