javascript是基于原型链的一种语言,想要理解原型和原型链,首先知道什么是对象,在javascript中一切皆对象,数组(Array)是对象,函数(Function)是对象。这里从构造函数谈起!
函数对象
通过new Function()
创建的对象都是函数对象
let fun1 = new Function("aa");
let fun2 = function(){};
function fun3(){};
以上三种都是函数对象
构造函数
构造函数是一种特殊的函数,用来构造对象的(一句废话)
// Person为构造函数
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){alert(this.name)};
}
let person1 = new Person("aa", 18, "dalaoshu");
let person2 = new Person("bb", 18, "zhuaxia");
构造对象分为四步
- new申请内存,创建对象
- 调用构造函数,构造函数有一个隐式参数,即this
- 刚创建出来的对象的引用赋值给this,有函数处理
- 在构造函数中利用
this.成员变量 = 值
来给对象添加成员
Person是构造函数,person1和person2都是构造函数Person的实例
person1.constructor === Person
原型对象
在javascript中定义一个对象的时候,对象中都会包含一条属性prototype
,该属相就是这个对象原型对象。
构造函数自身的属性和方法无法被共享,而原型对象的属性和方法可以被所有实例对象所共享。
//示例1
function Person() {
Person.prototype.name = 'xiaoming';
Person.prototype.age = 28;
Person.prototype.job = 'zhuaxai';
Person.prototype.sayName = function() {
alert(this.name);
}
let person = new Person();
person.sayName(); // 'xiaoming'
上述例子也可以改为
Person.prototype = {
name: 'xiaoming',
age: 28,
job: 'zhuaxia',
sayName: function() {
alert(this.name);
}
}
prototype
对于构造函数来说是他的属性,对于实例对象来说,是实例对象的原型对象
person.__proto__ = Person.prototype
person.__proto__.constructor = Person
原型链
读取对象的某个属性时,JavaScript引擎先寻找对象本身的属性,如果找不到,就到它的原型对象去找,如果还是找不到,就到原型对象的原型对象去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined
//示例
function Person(name){
Person.prototype.name = 'xiaoming';
Person.prototype.age = 28;
Person.prototype.job = 'zhuaxai';
this.name = name;
Person.prototype.sayName = function() {
console.log(this.name); // 对象本身的属性
console.log(this.age);// 对象本身没这个属性,所以是对象的原型对象的属性
}
}
let person = new Person("geigei");
person.sayName(); // 'xiaoming'
console.log(person.__proto__ === Person.prototype) // true
console.log(person.__proto__.constructor === Person) // true
constructor属性是原型对象上的一个属性,可以被所有实例对象所共享。要注意的是,prototype是构造函数的属性,而constructor则是构造函数的prototype属性所指向的那个对象,也就是原型对象的属性。由于constructor属性是一种原型对象和构造函数的关系,所以在修改原型对象的时候,一定要注意constructor的指向问题。
参考: