js面向对象编程/原型链/继承 —— javascript
目录
js面向对象编程
js面向对象编程不同于 java 的类和对象
javascript 不区分类和实例的概念,而是通过原型(prototype)来实现面向对象编程。
js声明的构造函数,类似于普通函数的声明,但又不同,
实例对象时,如果不写new,就是一个普通函数,它返回 undefined。
但是,如果写了new,它就变成了一个构造函数,它绑定的 this 指向新创建的对象,
并默认返回 this,也就是说,不需要在最后写return this;。
js原型链
代码段一:
function student(name){ this.name = name; this.say = function(){ console.log('my name:', this.name); } } let student1 = new student('student1'); let student2 = new student('student2');
console.log(student1.constructor === student.prototype.constructor) // true
橙色箭头表示原型链,其原型链为:
student1 --> student.prototype --> object.prototype --> null
当我们用 obj.xx
访问一个对象的属性时,javascript引擎先在当前对象上查找该属性,
如果没有找到,就到其原型对象上找,如果还没有找到,就一直上溯到object.prototype
对象,
最后,如果还没有找到,就只能返回undefined
。
共享方法
代码段二:
function student2(){ this.say = function(){ console.log('hi') } } console.log(new student2().say === new student2().say)
结果:
false
实例化的对象方法,虽然方法名称和代码完全一样,但是不同对象指向的不是同一个方法
需要创建一个共享的方法,
根据原型链图,需要将这个共享方法声明在 student2 的原型对象上,
xxx.prototype.xxx = function(){}
function student2(){ this.say = function(){ console.log('hi') } } student2.prototype.publicsay = function(){ console.log('public say'); } console.log(new student2().say === new student2().say) console.log(new student2().publicsay === new student2().publicsay)
结果:
false true
原型继承
学过 java 的都知道,类的继承通过 extends 会很容易实现,
但是 javascript 的原型继承有点麻烦,不过 class继承就很方便
function father(name){ this.say = function(){ console.log(name) } } function son(name){ father.call(this, name) } console.log(son.prototype.__proto__) // object
这样看似继承了,但是其原型链的指向并没有改变
其原型链图为:
要实现原型继承,看图的话很容易,只需要将 son 的原型对象的原型指向 father 的原型对象
要实现原型继承,这里有三种方法,
法一:
这个方法简介明了,但是不推荐直接通过 __proto__ 直接改变原型
function father(name){ this.say = function(){ console.log(name) } } function son(name){ father.call(this, name) } son.prototype.__proto__ = father.prototype; console.log(son.prototype.__proto__) // father
法二:
通过实例化 father 生成一个对象,
new father() 的原型会默认指向 father 的原型
通过修改 son 的 prototype 属性和 new father() 的 constructor 属性,
来绑定 son 和 new father() 之间的关系
function father(name){ this.say = function(){ console.log(name) } } function son(name){ father.call(this, name) } son.prototype = new father(); son.prototype.constructor = son; console.log(son.prototype.__proto__) // father
法三:
类似法二,声明一个中间对象来改变指向
mid.prototype = father.prototype; son.prototype = new mid(); son.prototype.constructor = son;
第一步,将 mid 的原型对象指向 father 的原型对象,
第二步,将 son 的属性 prototype 指向 mid,
此时代码上的 new mid(),实际上是 new father(),
第三步,将 son.prototype.constructor 也就是 mid.prototype.constructor 指向 son
看起来有点乱,看数字步骤,方便理解
function father(name){ this.say = function(){ console.log(name) } } function son(name){ father.call(this, name) } mid.prototype = father.prototype; son.prototype = new mid(); son.prototype.constructor = son; console.log(son.prototype.__proto__) // father
class继承
es6 提供了关键字 class,定义类变得更便捷
共享方法
class father{ // 构造方法 constructor(name){ this.name = name; } hello(){ console.log("hello", this.name) } } console.log(new father("f").hello === new father("f").hello) // true,共享方法
class继承
class father{ // 构造方法 constructor(name){ this.name = name; } hello(){ console.log("hello", this.name) } } class son extends father{ constructor(name){ super(name); } } console.log(son.prototype.__proto__) // father
上一篇: css滚动条样式修改
推荐阅读
-
JavaScript使用原型和原型链实现对象继承的方法详解
-
前端笔记知识点整合之JavaScript面向对象(一)Object&函数上下文&构造函数&原型链
-
js面向对象编程/原型链/继承 —— javascript
-
JS面向对象编程学习之构造函数的继承理解
-
总结javascript基础概念(三):js对象原型链
-
JS面向对象原理(二)------图解原型链(详)
-
javascript 面向对象编程基础:封装_js面向对象
-
javascript面向对象编程(二):继承
-
【JavaScript学习】面向对象的程序设计(6):原型式继承
-
【JavaScript学习】面向对象的程序设计(3):原型链继承