万物皆对象,万物皆为空(看下方关系图)
原型--保存所有子对象的共有属性值和方法的父对象;
原型链--由各级子对象的__proto__属性连续引用形成的结构;
三个属性:__proto__ ,constructor ,prototype
ES6以前写法
代码演示:
function Person(name, age) {
this.name = name
this.age = age
this.say = function () {
return '姓名:' + this.name; //console.log(this.name);
}
}
//当函数创建的时候就会携带上一个prototype属性,这个属性指向Person.prototype,也就是原型对象
Person.prototype.money = 20;
Person.prototype.run = function () {
console.log('跑步');
};
/**
* 注意!run()和money不是定义在Person上的,是原型对象Person.prototype的
* 错误用法:console.log(Person.money); //undefined
*/
//实例化对象
var p1 = new Person('张三', 12);
//1、实例化对象p1 带有__proto__属性,__?__这种形式的属性一般都是js内部属性,例[[scope]]
//2、p1.__proto__:js的内部属性都会携带Array Function Date...
console.log(p1.money);
console.log(p1.__proto__ === Person.prototype); //true
console.log(Person.prototype);
//Person.prototype 携带 constructor
console.log(Person.prototype.constructor === Person);
关系图
Function对象与Object对象之间的关系
Function是顶层的构造器,Object是顶层的对象
顶层现有null <-- Object.prototyepe <-- Function.prototype <-- Function (通过__proto__属性)
从原型上来说:Function继承了Object
从构造器上来说:Function构造了Object
function Object() { }
应用:继承
function Person(name, age) {
this.name = name
this.age = age
this.say = function () {
return '姓名:' + this.name; //console.log(this.name);
}
}
var p1 = new Person('张三', 12);
var p2 = {
name: '李四'
}
/**
* 注意!p1是Person实例化的对象,p1.__proto__指向原型对象Person.prototype
* 通过让对象p2的__proto__属性指向p1,构成一条原型链
* 对象p2则可以通过原型链访问p1和Person构造函数上的属性和方法
*/
p2.__proto__ = p1;
console.log(p2.say());//'李四',p2的name属性已重新赋值
console.log(p1.say());//'张三',p2不影响p1
ES6支持class继承
ES6的class只是对于function()的一种新的写法,不同点是类(class)的写法,以及类之间的继承关系(exten)。ES6的类与c++,java的类还是有所不同的
class Person {
constructor(name) {
this.name = name
}
sayHi() {
return `你好!${this.name}`
}
}
class Student extends Person{
constructor(name,number) {
super(name);
this.number = number
}
}
1、
const zhangsan = new Student('张三',1001);
console.log(zhangsan.name); //张三
console.log(zhangsan.sayHi()); //你好!张三
console.log(Student.prototype.sayHi()); //你好!undefined
console.log(zhangsan.__proto__===Student.prototype); //true
/**
* 函数和属性应该是定义在类的显式原型(.prototype)上的,而非类本身
* 因为在调用一个属性或方法的时候,该对象先在自身找,
* 若没有再到隐式原型(.__proto__)上找,指向类的显式原型(.prototype)
* */
2、
console.log(zhangsan instanceof Student); //ture
console.log(zhangsan instanceof Person); //ture
console.log(Student instanceof Person); //flase 子类和父类是继承关系,子类有自己的构造器
console.log(Student instanceof Object); //ture
console.log(Object instanceof Function); //ture
console.log(Person.__proto__===Function.prototype); //true
console.log(Function.__proto__===Function.prototype); //true
顶层的构造器依旧是Function,Object和Function的关系与之前所讲一致,重申:class只是一种新的写法形式,参考上面关系图
3、
/**
* 子类和父类的原型关系
* 子类的__proto__指向父类本身,而非父类的显式原型prototype
* 子类显式原型prototype的隐式原型__proto__指向父类的显式原型
* */
console.log(Student.__proto__===Person); // true
console.log(Student.__proto__===Person.prototype); //false
console.log(Student.prototype.__proto__ === Person.prototype) //true