Animal.call(this, name);到底是什么?(理解JS中的继承)
前言
在学习继承相关的知识点时,遇到了一个问题。
下面这段代码中的animal.call(this, name);
是什么意思?为什么它就表示继承到了父类animal的属性呢?
function animal(name) { this.name = name; } animal.prototype.say = function() { return this.name; } function cat(name, color) { animal.call(this, name); this.color = color; } cat.prototype = object.create(animal.prototype); cat.prototype.constructor = cat; var cat = new cat('小黄', 'yellow');
后来回顾了new操作符的知识点,这才豁然开朗。
一、了解new操作符
通过构造模式来创建对象的关键一步就是,它会根据构造函数创建实例对象。
另外,很重要的是,实例化的过程中,this会指向实例对象,这样就可以将对应的属性和方法挂载到实例对象上。
我们打印一下this,发现它确实是实例对象,而非默认的window。
function foo(name) { console.log(this); this.name = name; } var foo = new foo('mm');
二、了解call方法
是函数特有的,它用来改变this的指向。
这背后的意思就是:把一个函数的方法绑定到相应的对象上,于是这个对象就就可以调用它。
具体啥意思呢?看下代码:
function add(x, y) { console.log('绑定对象是', this); return x + y; } var res1 = add(1, 2); console.log(res1); var obj = {}; var res2 = add.call(obj, 3, 4); console.log(res2);
虽然obj没有add方法,但是它通过call方法就可以调用了。观察发现,this从window改变到了obj身上!
三、call方法与继承
大家想想,利用this被改变的这个特点,我们只要写成构造函数的样子,不就能把一系列的属性和方法悄无声息地挂载到obj上了吗?!
什么意思呢?比如this.name = name; 既然this改变成obj了,那么原来的代码就变成这样了 ===> obj.name = name;
看下代码:
function foo(name) { console.log('绑定对象是', this); this.name = name; this.say = function() { console.log(`我叫${this.name},我喜欢编程!`); } } foo(); // 直接调用foo,this指向window var obj = {}; console.log('调用call方法前的obj:',obj); foo.call(obj, 'mm'); console.log('调用call方法后的obj:',obj);
在改变了this指向后,属性和方法挂载到了对象上,这不就相当于一种继承吗?
四、继承
再回过头来看下起初的代码:
function animal(name) { this.name = name; } animal.prototype.say = function() { return this.name; } function cat(name, color) { animal.call(this, name); this.color = color; } cat.prototype = object.create(animal.prototype); cat.prototype.constructor = cat; var cat = new cat('小黄', 'yellow');
第一步,将cat函数的原型指向animal的原型对象,这样cat就继承了animal原型上的say方法;
cat.prototype = object.create(animal.prototype);
在改变了cat的原型对象后,它的constructor属性也随之改变,指向了animal,因此必须要把它转回来,所以,
第二步,将cat的原型对象指向本身(cat);
cat.prototype.constructor = cat;
第三步,实例化cat对象。
var cat = new cat('小黄', 'yellow');
- 首先实例化对象,此时的this绑定到了cat的实例对象;(然后依次执行以后的代码)
-
animal.call(this, name);
此时实例对象调用animal方法,传入参数name,这样实例对象上就有了name; -
this.color = color;
接下来是cat自身的属性color。将color挂载到实例对象上,这样实例对象上就有了color。 - 返回实例对象。
第四步,将实例对象赋值给cat。
最后,cat是否继承了animal,又是否有自己的属性color呢?
console.log(cat); console.log(cat.say());
ok,我们成功了。
五、总结
综上,理解animal.call(this, name);
的关键是:this绑定对象绑定的是那个实例对象,call方法实现了属性的继承。
当然,如果是共享的属性或方法,还是利用原型链来继承比较好~
推荐阅读
-
Animal.call(this, name);到底是什么?(理解JS中的继承)
-
深入理解Angular.JS中的Scope继承
-
js中关于原型链与继承的理解
-
理解Js中的继承 看这篇博客时务必画出子对象实例 子对象原型 子对象构造函数 父对象实例 父对象原型 父对象构造函数之间的关系
-
js中关于原型链与继承的理解
-
Animal.call(this, name);到底是什么?(理解JS中的继承)
-
javascript面向对象是什么?js中对象的理解
-
深入理解Angular.JS中的Scope继承
-
javascript面向对象是什么?js中对象的理解
-
js中的原型链、闭包四种作用、继承、命名空间、枚举类型是什么?