Javascript Good Part读书笔记-JavaScript继承
文章目录
继承(Inheritance)
伪类(Pseudoclassical)
当一个函数对象被创建时,这个函数的构造器会产生一个函数对象运行类似下面的代码:
1
|
this.prototype = {constructor: this}; |
例子,定义一个构造器,并在prototype上添加方法
1 2 3 4 5 6 7 8 9 |
var Mammal = function (name) { this.name = name; }; Mammal.prototype.get_name = function () { return this.name; }; Mammal.prototype.says = function () { return this.saying || ''; }; |
创建实例
1 2 |
var myMammal = new Mammal('Herb the Mammal'); var name = myMammal.get_name(); // 'Herb the Mammal' |
创建另一个伪类继承Mammal,通过定义该伪类的constructor
函数并且替换它的prototype
属性为Mammal的实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
var Cat = function (name) { this.name = name; this.saying = 'meow'; }; // Replace Cat.prototype with a new instance of Mammal Cat.prototype = new Mammal(); // Augment the new prototype with purr and get_name methods. Cat.prototype.purr = function (n) { var i, s = ''; for (i = 0; i < n; i += 1) { if (s) { s += '-'; } s += 'r'; } return s; }; Cat.prototype.get_name = function () { return this.says() + ' ' + this.name + ' ' + this.says(); }; |
1 2 3 4 |
var myCat = new Cat('Henrietta'); var says = myCat.says(); // 'meow' var purr = myCat.purr(5); // 'r-r-r-r-r' var name = myCat.get_name(); // 'meow Henrietta meow' |
使用前面定义的method
方法定义一个inherits
方法:
1 2 3 4 |
Function.method('inherits', function (Parent) { this.prototype = new Parent(); return this; }); |
因为inherits
和method
方法都返回this
,我们可以通过及联调用的方式实现Cat
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var Cat = function (name) { this.name = name; this.saying = 'meow'; }.inherits(Mammal) .method('purr', function (n) { var i, s = ''; for (i = 0; i < n; i += 1) { if (s) { s += '-'; } s += 'r'; } return s; }) .method('get_name', function () { return this.says() + ' ' + this.name + ' ' + this.says(); }); |
伪类继承存在的问题
- 没有私有属性/方法(JavaScript所有属性都是公有的)。
- 不能访问父类的方法。
- 如果调用的时候忘记了
new
(没有以构造函数的方式调用),则this
不能被绑定到新创建的对象实例(this将会被绑定到全局对象)。
对象说明符(Object Specifiers)
当一个构造器有非常多的参数时,参数的顺序会变的非常难记,这时候可以通过对象描述符代替。
例如:
1
|
var myObject = maker(f, l, m, c, s); |
可以写为:
1 2 3 4 5 6 7 |
var myObject = maker({ first: f, last: l, middle: m, state: s, city: c }); |
原型(Prototypal)
基于原型的继承方式比经典的继承在概念上更为简单,并且更容易理解。
示例
1 2 3 4 5 6 7 8 9 |
var myMammal = { name : 'Herb the Mammal', get_name : function () { return this.name; }, says : function () { return this.saying || ''; } }; |
创建对象实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
var myCat = Object.create(myMammal); myCat.name = 'Henrietta'; myCat.saying = 'meow'; myCat.purr = function (n) { var i, s = ''; for (i = 0; i < n; i += 1) { if (s) { s += '-'; } s += 'r'; } return s; }; myCat.get_name = function () { return this.says() + ' ' + this.name + ' ' + this.says(); }; |
函数化(Functional)
通过模块化的方式实现封装,可通过如下4步实现
创建一个对象,创建对象的方式:
- 字面符
- 通过
new
调用构造器 - 从一个已经存在的对象使用
Object.create
方法新建一个实例 - 调用一个函数返回一个对象
定义私有的实例变量和方法(可选)
为创建的对象增加方法(这鞋方法有权限去访问底2步中定义的变量/方法)
返回新建的对象。
伪代码如下:
1 2 3 4 5 6 7 8 |
var constructor = function (spec, my) { var that, other private instance variables; my = my || {}; Add shared variables and functions to my that = a new object; Add privileged methods to that return that; }; |
示例
1 2 3 4 5 6 7 8 9 10 11 |
var mammal = function (spec) { var that = {}; that.get_name = function () { return spec.name; }; that.says = function () { return spec.saying || ''; }; return that; }; var myMammal = mammal({name: 'Herb'}); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var cat = function (spec) { spec.saying = spec.saying || 'meow'; var that = mammal(spec); that.purr = function (n) var i, s = ''; for (i = 0; i < n; i if (s) { s += '-'; } s += 'r'; } return s; }; that.get_name = function(){ return that.says() + ' ' + spec.name + ' ' + that.says(); }; return that; }; var myCat = cat({name: 'Henrietta'}); |
访问父类方法
1 2 3 4 5 6 7 |
Object.method('superior', function (name) { var that = this, method = that[name]; return function () { return method.apply(that, arguments); }; }); |
示例
1 2 3 4 5 6 7 8 9 10 |
var coolcat = function (spec) { var that = cat(spec), super_get_name = that.superior('get_name'); that.get_name = function (n) { return 'like ' + super_get_name() + ' baby'; }; return that; }; var myCoolCat = coolcat({name: 'Bix'}); var name = myCoolCat.get_name(); // 'like meow Bix meow baby' |
文章作者 binbin wen
上次更新 2019-11-14