原型
- 实例化出来的对象继承构造函数的原型。
- 所有这个构造函数构造出来的对象,都继承于他的原型。 ```javascript function Person() { }
//给Person原型上定义一个name赋值为Lucy Person.prototype.name = ‘Lucy’;
//实例化Person var p = new Person(); console.log(p);
<a name="uaom5"></a>## 继承1. 实例化对象继承了原型链上的**所有**属性。1. 但是实例化对象**并没有继承自己本身含有的属性**。```javascriptProfessor.prototype = {name: 'Mr Zhang',tSkill: 'JAVA'}function Professor() {}var professor = new Professor();/*** professor:{* __proto__:{* name:'Mr Zhang',* tSkill:'JAVA'* }* }*/function Teacher() {this.name = 'Mr Li';this.mSkill = 'JS/JQ';}//将Professor的实例化对象赋值给Teacher当原型。Teacher.prototype = professor;//实例化Teachervar teacher = new Teacher();console.log(teacher)//将Teacher的实例化对象赋值给Student当原型。Student.prototype = teacher;function Student() {this.name = 'xiao wang';this.pSkill = 'HTML/CSS';}// 实例化studentvar student = new Student();//xiao wang 如果自身有这个属性。就不会往原型链上去找属性。console.log(student.name);
apply,call
- call,apply都是通过改变this指向的、来借用别人的属性和方法。并不是继承。 ```javascript Teacher.prototype.wife = ‘Mrs Liu’;
function Teacher(name,mSkill) { this.name = name; this.mSkill = mSkill; }
function Student(name,mSkill,age,major) { Teacher.apply(this, [name, mSkill]);//通过改变this指向来借用Teacher的属性和方法。 this.age = age; this.major = major; }
//实例化student var student = new Student(‘Axi’, ‘HTML’, 16, ‘Computer’); console.log(student);//apply,call的方式并没有让 student 继承到Teacher的prototype 这种方式构造的student无法获取到teacher原型上的属性。
- Student.prototype = Teacher.prototype 这种方式 让student 继承了teacher 的原型。并不会继承teacher的属性```javascriptfunction Teacher() {this.name = 'Mr Wang';this.mSkill = 'JS';}//将Teacher的原型重新赋值。Teacher.prototype = {pSkill: 'JQ'}//实例化一个teachervar teacher = new Teacher();//将Student的原型赋值为Teacher.prototype。//这种方式 让student 继承了teacher 的原型上的方法和属性。但是并不会继承teacher的属性(name,mSkill)Student.prototype = Teacher.prototype;//学生构造函数function Student() {//构造函数隐式申明了一个this;并且隐式返回了一个this;this.name = 'Mr Li';}var student = new Student();console.log(student.name);//undefinedconsole.log(student.mSkill);//undefinedconsole.log(student.pSkill);//JQ;//添加学生构造函数上的属性Student.prototype.age = 18;//老师的构造函数原型上也多了一个age属性。说明他俩prototype指向一个对象。console.log(Teacher.prototype.age)
圣杯模式
方案:构建一个新的构造函数,这个构造函数去继承Origin的原型。而Target则去接收新的构造函数实例化的对象。这个时候Target的原型和Origin的原型就不是同一个对象了。而Target可以继承Origin的属性和方法。
// 声明一个构造函数Teacher。function Teacher() { }//父类// 往Teacher的原型上添加一个age属性,并且赋值为19Teacher.prototype.age = 19;// 申明一个构造函数Studentfunction Student() { }//子类// 将缓冲类的Buffer的原型赋值为Teacher的原型。Buffer.prototype = Teacher.prototype;function Buffer() { }//缓冲类//创建一个buffer实例。var buffer = new Buffer();//缓冲类实例//将这个实例赋值给Student的原型。Student.prototype = buffer;// 实例化Teachervar teacher = new Teacher();// 实例化studentvar student = new Student();// 往Student原型上添加sex 相当于给buffer添加sex属性。Student.prototype.sex = 'male';// 往Teacher原型上添加major 相当于给Buffer.prototype添加sex属性。Teacher.prototype.major = 'JAVA';console.log(student);console.log(teacher);//这个操作就不会造成修改一个构造函数原型上的属性。另外一个构造函数不会因此改变。
圣杯模式的企业级写法
Teacher.prototype.name = 'Mr Wang';function Teacher() {}function Student() { }inherit(Student, Teacher);//企业级写法function inherit(Target,Origin) {function Buffer() { }//缓冲区Buffer.prototype = Origin.prototype;Target.prototype = new Buffer();//Buffer实例化赋值给目标源的prototypeTarget.prototype.constructor = Target;//还原构造器。函数原型上的构造器一般都指向本身。Target.prototype.super_class = Origin;//记录超类。在目标函数上记录继承源;}
构造函数形成的闭包
function Compute() {var num = 10;this.add = function () {num++;console.log(num);}this.minus = function () {num--;console.log(num);}// 构造函数被实例化的时候隐式返回了一个this。这个this中包含了num,add,minus属性或方法。// 这个构造函数被执行的时, this.add,this.minus被定义。此时this.add,this.minus创建了自己的作用域和作用域链,作用域链的第0位存的是Compute的AO,第二位是GO。// 构造函数被实例化时 隐式返回了this。this中的add 和minus 都被返回出去了。所以形成了闭包。}var cp = new Compute();//实例化这个函数的时候相当于这个函数执行了一遍cp.add();//11//cp.add();//12cp.add();//13

