四、面向对象编程
1.“JavaScript的原型链和Java的Class区别就在,它没有Class的概念,所有对象都是实例,所谓继承关系不过是把一个对象的原型指向另一个对象而已”:
var Student = {
name: 'Robot',
height: 1.2,
run: function () {
console.log(this.name + ' is running...');
}
};
var xiaoming = {
name: '小明'
};
xiaoming.__proto__ = Student;
xiaoming.name; // '小明'
xiaoming.run(); // 小明 is running...
2.注意“最好不要直接用对象名.__proto__
改变一个对象的原型,而且低版本的IE也无法使用__proto__
,Object.create()
方法可以传入一个原型对象,创建并返回一个基于该原型的新对象”
3.原型链示例如下,创建一个数组对象,数组arr的原型指向数组的原型:
var arr = [1, 2, 3];
// 原型链
arr的原型对象 ----> Array.prototype ----> Object.prototype ----> null
arr的原型就是Array.prototype:
Object.getPrototypeOf(arr) === Array.prototype; // true
4.重点学习以函数的形式new一个对象的方式,以及和原型链相关的内容。
5.“为了区分普通函数和构造函数,按照约定,构造函数首字母应当大写,而普通函数首字母应当小写,这样,一些语法检查工具如jslint将可以检测到漏写的new
。”
6.练习请利用构造函数定义Cat
,并让所有的Cat对象有一个name
属性,并共享一个方法say()
,返回字符串'Hello, xxx!'
:
'use strict';
function Cat(name) {
this.name = name;
}
Cat.prototype.say = function () {
return `Hello, ${this.name}!`
}
// 测试:
var kitty = new Cat('Kitty');
var doraemon = new Cat('哆啦A梦');
if (kitty && kitty.name === 'Kitty'
&& kitty.say
&& typeof kitty.say === 'function'
&& kitty.say() === 'Hello, Kitty!'
&& kitty.say === doraemon.say
) {
console.log('测试通过!');
} else {
console.log('测试失败!');
}
7.“把继承这个动作用一个inherits
函数封装起来,可以隐藏用于桥接的函数F
的定义,并简化代码”:
function inherits(Child, Parent) {
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
假设Cat
继承了Animal
:
var c = new Cat("kitty");
// 验证继承关系
c instanceof Cat; //true
c instanceof Animal; //true
课程总结js的原型继承实现方式如下三步:
1)定义新的构造函数,并在内部用call()
调用希望“继承”的构造函数,并绑定this
;
2)借助中间函数F
实现原型链继承,最好通过封装的inherits
函数完成;
3)继续在新的构造函数的原型上定义新方法。
老规矩翻评论,大都比较蒙比,这个原型继承相较于java来说太绕了,而且ES6中就添加了class关键字,有class
继承了,这个原型继承可以实际用到的时候再好好研究。
8.看了一下class继承部分,“不是所有的主流浏览器都支持ES6的class
,如果一定要现在就用上,就需要一个工具把class
代码转换为传统的prototype
代码,比如Babel这个工具。”
9.练习利用class
重新定义Cat
,并让它从已有的Animal
继承,然后新增一个方法say()
,返回字符串'Hello, xxx!'
:
'use strict';
class Animal {
constructor(name) {
this.name = name;
}
}
class Cat extends Animal {
constructor(name) {
super(name);
}
say() {
return `Hello, ${this.name}!`
}
}
// 测试:
var kitty = new Cat('Kitty');
var doraemon = new Cat('哆啦A梦');
if ((new Cat('x') instanceof Animal)
&& kitty
&& kitty.name === 'Kitty'
&& kitty.say
&& typeof kitty.say === 'function'
&& kitty.say() === 'Hello, Kitty!'
&& kitty.say === doraemon.say)
{
console.log('测试通过!');
} else {
console.log('测试失败!');
}