1.call()
call()方法接受两个参数,obj和arg
比如functionA.call(obj,arg) 就是说现在运行(执行)functionA这个方法,但是functionA里面的方法不是为它以前的对象而运行了,把functionA的this强行改变成了obj
obj成为functionA中的this,然后来运行functionA这个方法,而arg是传给functionA的参数
function Student(props) {
this.name = props.name || 'Unnamed'; } Student.prototype.hello = function () { alert('Hello, ' + this.name + '!'); }
function PrimaryStudent(props) { Student.call(this, props); this.grade = props.grade || 1; }
比如上面的代码,先定义了Student
方法,然后定义了PrimaryStudent
方法
在PrimaryStudent中,
Student.call(this, props);
指的是把this——也就是PrimaryStudent
对象作为运行时的那个this,把
Student
来运行
props传给Student作为参数,
这个方法,运行出来的结果是什么呢
Student
.name=
PrimaryStudent
props.name //这个props是传进来那个props
然后
PrimaryStudent
.prototype.hello = function () { alert('Hello, ' + this.name + '!'); } 它还获得了一个写在原型里的方法
则
PrimaryStudent
这个函数运行下来的结果相当于
functionPrimaryStudent
(props){
this.name = props.name || 'Unnamed';
this.prototype.hello = function () { alert('Hello, ' + this.name + '!'); }
}
这就是call方法
它会运行一个函数,然后告诉这个函数你现在得用我给你的对象来运行你的那套方法,返回出什么东西是什么东西
2.原型继承
而原型继承呢
一般我们会先定义一个方法 比如刚才的Student
Student
方法里有属性,有定义在原型里的方法
然后我们想继承Student
,我们定义出一个新的函数 littleStudent
在这个新的函数内部我们 Student.call(this,arg) 在这里this指的是littleStudent,按上面定义的Student函数(内部拿this写属性和方法),我们会获得一个littleStudent它内部有Student的那些属性和方法
等于Student在我们littleStudent内部执行了一遍,并且是为我们造属性和方法的,我们littleStudent现在也有这些方法了
但这样是继承吗?Student日后有改变,我们的littleStudent会有改变吗,不会
因为我们只是拿call让Student
给我们也造了一套属性的方法,我们littleStudent
的原型仍然指向littleStudent.protptype
当前的原型链是职业的 new littleStudent
() ----> littleStudent
.prototype ----> Object.prototype ----> null 跟Student
没有关系
需要变成这样 new littleStudent
() ----> littleStudent
.prototype ----> Student.prototype ----> Object.prototype ----> null
那么怎么继承呢
先创建一个空函数F(){ }
把这个空函数的原型指向Student
的原型:F.prototype = Student.prototype;
然后把littleStudent的原型指向F的实例:littleStudent
.prototype=new F();
; 则littleStudent
的原型里包含了student原型里的所有内容
然后把littleStudent
原型的构造函数修复为littleStudent
:littleStudent
.prototype.constructor = littleStudent
; 因为之前littleStudent
.prototype=new F()
则new F().constructor
指向的是构造函数F
然后我们就可以继续在littleStudent对象的原型上添加方法和属性了
littleStudent
.prototype.getGrade = function () {
return this.grade; };
而这并不会影响Student的原型,因为我们在这儿添加方法相当于是在new F()上添加方法
至此我们又给littleStudent
继承了Student的原型,又可以随意给它扩展,这就完成了一次继承