传统的基于class的面向对象语言如Java中,都有两个基本概念:编程
Student xiaoming = new Student()
而JS不区分类和实例的概念,它经过原型(prototype)实现面向对象。JS建立对象是用原型,实现继承也是用原型。函数
建立对象:this
var Student = {name: 'abc', height: 1.7}; var xiaoming = {name: 'xiaoming'}; xiaoming._proto_ = Student;
JS对每一个建立的对象都会设置一个原型,指向它的原型对象。
当使用obj.***
访问一个对象的属性时,JS如今当前对象上查找该属性;若是没找到,就到其原型对象上找;若是还没找到,就一直上溯到Object.prototype
这个原型对象;最后,若是还没找到,就返回undefined
。这个过程能够表示为一个原型链。spa
// 构造函数对象 function Student(name) { this.name = name; //这里设置了每一个对象的属性 } // 原型对象 Student.prototype.hello = function() { alert('Hello, ' + this.name); //这里设置了全部对象共享的hello函数,经过继承得到 } // 实例对象 var xiaoming = new Student('小明'); var xiaohong = new Student('小红');
原型链以下(图中红色箭头是原型链):prototype
xiaoming \
xiaohong -- Student.prototype ----> Object.prototype ----> nullcode
补充:
见犀牛书对象
Java中,继承的本质是:扩展一个已有的Class,生成一个新的Subclass。因为Java严格区分类和实例,继承其实是类型的扩展。blog
而JS没法直接扩展一个Class,由于不存在Class这种类型,JS采用的是原型继承。继承
考虑基于Student
扩展出PrimaryStudent
,原型链必须修改成这样:ip
new PrimaryStudent() ----> PrimaryStudent.prototype ----> Student.prototype ----> Object.prototype ----> null
实现方法:
// PrimaryStudent的构造函数 function PrimaryStudent(props) { Student.call(this, props); this.grade = props.grade || 1; } // 引入中间对象:空函数F function F() {} F.prototype = Student.prototype; // 修改两个属性,以实现上述原型链 PrimaryStudent.prototype = new F(); PrimaryStudent.prototype.constructor = PrimaryStudent; // 在PrimaryStudent的原型对象上定义方法 PrimaryStudent.prototype.getGrade = function() { return this.grade; } // 建立子类对象 var xiaoming = new PrimaryStudent({name: '小明', grade: 60}); // 验证原型 xiaoming.__proto__ === PrimaryStudent.prototype; //true xiaoming.__proto__.__proto__ === Student.prototype; //true
原型链图示: