一、原型
prototype就是英语“原型”的意思。原型是构造函数创建对象的原始模型
原型的特点:
- 原型也是对象,原型是函数对象的一个属性。
- 原型自带constructor属性, constructor指定构造函数。
- 构造函数创建出的对象会继承原型的属性和方法。
在JavaScript中,任何一个函数,都有一个prototype属性,指向一个对象。打印prototype属性,你会发现这个属性指向一个空对象。打印prototype的类型,发现是object类型。
1.构造函数中prototype
在传统的 OOP 中,首先定义“类”,此后创建对象实例时,类中定义的所有属性和方法都被复制到实例中。在 JavaScript 中并不如此复制,而是在对象实例和它的构造器之间建立一个链接(它是__proto__属性,是从构造函数的prototype属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法。
1. 每个函数上面都有一个属性(prototype)指向了函数的原型对象(Person.prototype)。
代码例:👇
<script>
function Person (name){
this.name = name;
this.sayhai = function(){
console.log('我的名字叫'+this.name);
}
}
Person.prototype.eat = function(){
console.log('会吃饭')
}
let a = new Person('zs');
console.log(a)
</script>
图解:👇
当一个对象被new出来的时候,不仅仅执行了构造函数里面的语句,我们的感觉,构造函数的原型中,所有的属性也加给了这个对象
prototype一定是函数的属性,但这个函数是一个构造函数的时候,那么它new出来的对象,将以他的原型那个对象为new出来的实例的原型对象
2.实例中__proto__属性
实例中的__proto__指向的是原型对象
当一个对象被new出来的时候,不仅仅执行构造函数的语句,也会吧这个函数的__proto _ 指向构造函数的prototype
如上面的代码所示
a.__proto__👇
注意:
任何一个对象,都有
__proto__
属性,这个属性是Chrome自己的属性,别的浏览器不兼容,但是别的浏览器也有原型对象,只不过不能通过__proto__
进行访问而已。这是属性指向自己的原型对象。
3.原型的终点就是null
JS的世界中只有一个对象没有原型对象,这个对象就是Object.prototype。
Object是一个函数,是系统内置的构造函数,用于创造对象的。Object.prototype是所有对象的原型链终点。
所以,当我们在一个对象上打点调用某个方法的时候,系统会沿着原型链去寻找它的定义,一直找到Object.prototype。
特别的:
prototype我们称为“原型”,只有函数有原型。
__proto__
我们称为“原型对象”,任何对象都有原型对象。
二、原型链
只要是对象,一定有原型对象,就是说只要这个东西是个对象,那么一定有
__proto__
属性。我们想实例的原型对象也是一个对象,那么我们迫切的想看看这个原型对象的原型对象.如果这理论没有问题的话,这个原型对象应该也有
__proto__
指向他的原型对象吧.
function Student(){
}
var xiaoming = new Student();
// 原型对象的原型对象
console.log(xiaoming.__proto__.__proto__);
// 原型对象的原型对象的构造函数是谁
console.log(xiaoming.__proto__.__proto__.constructor); //Object
// 那我们看看还能不不能再向上查原型对象
console.log(xiaoming.__proto__.__proto__.__proto__);
// 结果为null
通过上面的示例, 发现开始的一句话其实是错误的.
JS的世界中只有一个对象没有原型对象,这个对象就是Object.prototype。
现在就能想明白一些事情,一个对象天生带一些属性和方法
比如:
function Student(){
}
var xiaoming = new Student();
// 小白马上可以调用toString()方法
console.log(xiaoming.toString());
// 打印 "[object Object]"
// 这个方法是小明原型对象的原型对象身上的方法,我们可以看下
console.log(xiaoming.__proto__.__proto__);
Object是一个函数,是系统内置的构造函数,用于创造对象的。Object.prototype是所有对象的原型链终点。
所以,当我们在一个对象上打点调用某个方法的时候,系统会沿着原型链去寻找它的定义,一直找到Object.prototype。
Object.prototype是所有对象原型链的终点,现在我强行给它添加一个属性
Object.prototype.sayHello = function(){
alert("你好")
}
// 现在小明能sayHello
xiaoming.sayHello();
// 岂止xiaoming能sayHello 数组也能sayHello
var arr = [1,2,3];
arr.sayHello();
// 然后世界上一切都能sayHello了
"么么哒".sayHello();
无奈源于不够强大