JavaScript之原型和原型链
JavaScript之原型和原型链
在JavaScript的学习过程中,原型链肯定是一个很重要的知识点,下面我们就来深入的去看一下原型链
原型
首先看一个很简单的例子
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = function () {
console.log("i am "+this.name);
}
}
Person.prototype.sayAge = function () {
console.log("i am "+this.age);
}
var person1 = new Person("ljm",18)
person1.sayAge();
person1.sayName();
var person2 = new Person("lll",20);
person2.sayAge();
person2.sayName();
控制台输出的是,和大多数人预想的一样,输出了两个person的年龄和姓名
在这个过程中我们创建了两个实例对象(person1,person2),有一个构造函数(Person)和原型(Person.prototype),那么他们之间的关系应该是这样的
在这里插入图片描述
在这个关系上我们可以看出
- 每个函数上面都有一个属性(prototype)指向了函数的原型对象(Person.prototype)。
- 每个实例上面都有一个隐式原型(proto)指向了函数的原型对象,如本利的p1对象有一个隐式原型也指向了Person.prototype对象。
- 每个函数的原型对象上面都有一个constructor属性,指向了构造函数本身。
实例的(person1,person2)的__proto__
也是Person.prototype
那么在实例访问属性或者方法的时候应该遵循什么样的原则?
- 如果实例上面存在,就用实例本身的属性和方法。
- 如果实例上面不存在,就会顺着
__proto__
的指向一直往上查找,找到就停止,找不到就报错。
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = function () {
console.log("i am "+this.name);
}
}
Person.prototype.sayAge = function () {
console.log("我是原型上的sayAge");
}
var person1 = new Person("ljm",18)
person1.sayAge = function () {
console.log("我是person1上的sayAge")
}
person1.sayAge();
person1.sayName();
var person2 = new Person("lll",20);
person2.sayAge();
person2.sayName();
person2.sayHello();
那么输出的结果就是
如果找不到这个方法,就报错
在这里插入图片描述
虽然person1和person2都输出了sayAge方法,可是这两个方法是不一样的
原型链
那么在刚刚这个输出sayAge过程大概可以这样描述:
在person1上有sayAge,所以输出的就是person1上的sayAge
在person2上没有sayAge,但是在person2的原型上有sayAge,所以输出的就是person2上的sayAge
简单点说就是,如果我自己有,我就用我自己的;如果我没有,则去我的上一级找;这样就形成了一条原型链。上一节中Person的原型其实还有一属性__proto__
,他指向了上一级Object的原型对象。
Object.prototype可以说是原型中的最高层,那么最终原型链应该是这样的
原型和实例之间的判断
-
使用instanceof
console.log(person1 instanceof Person)//true console.log(person1 instanceof Object)//true
-
使用isPrototypeOf()方法
console.log(Object.prototype.isPrototypeOf(person1))//true console.log(Person.prototype.isPrototypeOf(person1))//true console.log(Function.prototype.isPrototypeOf(person1))//false
在ES6中的新运用
在ES6中,新运用了class来对JavaScript的语法更加加以完善。
在其他语言中,例如java,就有类(class),里面有构造函数(constructor),属性,方法等
所以在ES6中,为了弥补之前的不足,新推出了class
在以前的js中,生成一个对象实例,需要先定义构造函数,然后通过prototype 的方式来添加方法,再生成实例,但是现在ES6可以这样写
class Person{
constructor(age,name){
this.age = age;
this.name = name;
}
sayName(){
console.log("我是"+this.name)
}
}
var person1 = new Person(18,"ljm")
console.log(person1.name)//ljm
console.log(person1.age)//18
person1.sayName()//我是ljm
在ES5中原本的构造函数被constructor 替代,本来需要定义在prototype上面的,方法直接定义在class里面即可。
继承
在ES6中可以使用extends来继承类(和java差不多)
class Student extends Person{
constructor(age,name,className){
super(age,name);
this.className = className;
}
sayClass(){
console.log("我是"+this.className)
}
}
var student1 = new Student(19,"ljm","四班");
console.log(student1.age)//19
console.log(student1.name)//ljm
console.log(student1.className)//四班
student1.sayClass()//我是四班
student1.sayName()//我是ljm
在ES5中prototype的继承
function Person(age,name) {
this.age = age;
this.name = name;
}
Person.prototype.sayName = function () {
console.log("我是"+this.name)
}
function Student(age,name,className) {
Person.call(this,age,name);
this.className = className;
}
Person.prototype.constructor = Student;
Student.prototype = new Person;
Student.prototype.sayClass = function () {
console.log("我是"+this.className)
}
var student1 = new Student(19,"ljm","四班")
student1.sayClass();
student1.sayName();
在ES6语法上更加便捷
上一篇: 急高分请问MySQL查询有关问题