传统方法过渡到ES6去优雅地实现JavaScript的继承
众所周知,面向对象编程有三个重要的概念: 封装、继承、多态。而JS作为面向对象的弱类型语言,应该说是基于对象的语言,正如常说的,JS的世界里,万物皆对象。虽然JS本身不是面向对象的语言,我们可以通过模拟的方法,来实现类似JAVA式的类继承,之后使用Es6语法,使我们更加简单方便的实现类的继承。
1、创建一个自定义对象
//构造函数
function People(name,age){
this.name = name;
this.age = age;
}
//定义原型对象
People.peototype={
getName : function(){
return this.name;
},
getAge : function(){
return this.age;
}
} var p1 = new People('leaf',10);
console.log(p1.getName()) //leaf
2、当执行 var p1 = new People('leaf',10);内部主要做了这几件事
1. 创建新的空对象(new Object());
2. 设置新对象的__proto__继承构造函数的prototype (p1.__proto__===People.prototype );
3. 将这个对象通过this关键字传递到构造函数中并执行构造函数。
4. 将这个对象赋值给p1.
实现一个new的方法:
function create() {
// 创建一个空对象
let obj = new Object();
//获取构造函数
let Constructor = [].shift.call(arguments)
//连接到原型
obj.__proto_ = Constructor.prototype;
//绑定this
let result = Constructor.apply(obj, arguments)
//返回新对象
return typeof result === 'object' ? result : obj;
} function People(name, age) {
this.name = name;
this.age = age;
}
let p1 = create(People, 'leaf', 10);//调用自定义create实现new
console.log(p1.name) //leaf
console.log(p1.age) //10
3、简单的继承,看看
创建student类,它从People继承了原型prototype中所有的属性。
function Student(name, age, score) {
this.name = name;
this.age = age;
this.score = score;
}
将Studen原型指向Person的一个实例(其实就是Student.prototype里的__proto__指向了People的实例中的__proto__,
而People的实例中的__proto__又指向了People.prototype)。
因为People的实例可以调用People原型中的方法, 所以Studen的实例也可以调用Person原型中的所有属性。
Studen.prototype = new Person();
Student.prototype.constructor = Student; //避免实例的constructor属性指向Object函数
Studen.prototype.getScore= function() { return this.score; };
var p1 = new Employee("leaf", "12", "100");
console.log(p1.getName()); // "leaf
4、三种的方法存在的问题
1、在创建Student构造函数和原型时,就对Pelple进行了实例化,这是不合适的。
2、Student的构造函数没法调用父类Person的构造函数,导致在People构造函数中对name和age属性的重复赋值。
3、Student中的函数会覆盖Pelple中的同名函数,没有重载的机制.
5、修复之后更加优雅地继承
//构造函数
function People(name,age){
this.name = name;
this.age = age;
}
//定义原型对象
People.prototype={
constructor : People,
getName : function(){
return this.name;
},
getAge : function(){
return this.age;
}
} //定义一个Student类
function Student(name,age,score){
//调用Peopel构造函数,this指向了People
People.apply(this,arguments);
this.score=score;
} Student.prototype = {
constructor :Student,
getScore:function(){
return this.score;
}
} 让Student的原型对象继承People的原型对象
Object.setPrototypeOf(
Student.prototype, People.prototype
); var p2 = new Student('kafu',10,99);
console.log(p2.getScore());//99
console.log(p2.getName()); //kafu
console.log(Student.prototype.constructor==Student); //true
setPrototypeOf的polyfill
Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) {
obj.__proto__ = proto;
return obj;
}
6、传统方法小结
主要利用两点
1、在子类型构造函数中调用父类型构造函数,改变this的指向。
注意:可以使用call(this,参数属性)、apply(this,[参数数组])
2、利用Object.setPrototypeOf()
注意:该方法的Polyfill
Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) {
obj.__proto__ = proto;
return obj;
}
7、ES6实现类的继承
//定义People类
class People{
//构造函数
constructor(name,age){
this.name = name;
this.age = age;
} //原型上的方法
getName(){ //没有function哦
return this.name;
} getAge(){
return this.age;
}
}
//创建Student类并去继承People类
class Student extends People{
constructor(name, age, score){
super(name, age); //调用父类型的构造方法
this.score = score;
} getScore(){
return this.name+'的成绩是:'+this.score;
} } //usage
var p3 = new Student('kafu',10, 99);
console.log(p3.getScore());
8、es6方法的总结
1、es6中的extends其实就像传统方法中的
Object.setPrototypeOf(
Student.prototype, People.prototype
);
让子元素的原型继承父元素的原型
2、es6中的super()其实就像传统方法中 People.apply(this,arguments);借用父类中的构造函数。
3、可见深刻理解传统方法之后,对掌握好es6的新语法是有很大的帮助的。
传统方法过渡到ES6去优雅地实现JavaScript的继承的更多相关文章
- koa 基础(十八)es6中的类、静态方法、继承
1.app.js /** * es6中的类.静态方法.继承 */ // 定义Person类 class Person { constructor(name, age) { /*类的构造函数,实例化的时 ...
- ES6的优雅方法
1.箭头函数 // ES5 var selected = allJobs.filter(function (job) { return job.isSelected(); }); // ES6 var ...
- ES6 class类 静态方法及类的继承
一.class类 ES6之前都是定义函数以及函数的原型对象实现类型, 如果想要实现共享构造函数成员,可以用prototype来共享实现 ES6出现之后,使用class类的概念来实现原型的继承 二,静态 ...
- 最优雅,高效的javascript字符串拼接
这种方式是es6的语法.使用键盘1左边的那个字符 `` 拼接, 再加上js自带的模板引擎拼接字符串非常快速.这东西也没什么高深的,看几个例子就懂了. console.log(`<xml> ...
- 优雅绝妙的Javascript跨域问题解决方案
关于Javascript跨域问题的解决方案已在之前的一片文章中详细说明,详见:http://blog.csdn.net/sfdev/archive/2009/02/13/3887006.aspx: 除 ...
- [转] 怎样快速而优雅地遍历 JavaScript 数组
我们一般用循环来遍历数组,而循环一直是 JavaScript 性能问题的常见来源,有时循环用得不好会严重降低代码的运行速度.例如,遍历数组时,我们会很自然地写出下面这种代码: // 未优化的代码1 v ...
- ES6学习笔记八:类与继承
一:Class ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板.通过class关键字,可以定义类. 定义“类”的方法的时候,前面不需要加上function这个关键 ...
- 如何优雅的移植JavaScript组件到Blazor
Blazor作为一个新兴的交互式 Web UI 的框架,有其自身的优缺点,如果现有的 JavaScript 组件能移植到 Blazor,无疑让 Blazor 如虎添翼,本文就介绍一下自己在开发 Bul ...
- Python爬虫:更加优雅的执行JavaScript(PyV8)
https://www.jianshu.com/p/c534d6eb881a?utm_source=oschina-app
随机推荐
- 新概念英语(1-29)Come in, Amy.
How must Amy clean the floor? A:Come in, Amy. Shut the door, please. This bedroom's very untidy. B:W ...
- CSS中容易混淆的伪元素类型和用法
:first-of-type 匹配属于其父元素的第一个特定类型的子元素. 1.例子 <head> <meta charset="UTF-8"> <ti ...
- CentOS7配置php7.0支持redis
配置之前应该是环境已经搭好了,phpinfo的页面可以加载出来. 使用git clone下载git上的phpredis扩展包 [root@VM_103_117_centos ]#git clone ...
- 前段 format方法
a.为字符串创建format方法,用于字符串格式化 String.prototype.format=function (arg) { //console.log(this,arg); //this,当 ...
- jacascript 构造函数、原型对象和原型链
前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 先梳理一下定义: 我们通常认为 object 是普通对象,function 是函数对象: Function ...
- C# 类型、存储和变量
如果广泛地描述C和C++程序的源代码的特征,可以说C程序是一组函数和数据类型,C++程序是一组函数和类,然而C#程序是一组类型声明. 既然C#程序就是一组类型声明,那么学习C#就是学习如何创建和使用类 ...
- java学习历程,一年三年五年计划
学习这一部分其实也算是今天的重点,这一部分用来回答很多群里的朋友所问过的问题,那就是你是如何学习Java的,能不能给点建议?今天我是打算来点干货,因此咱们就不说一些学习方法和技巧了,直接来谈每个阶段要 ...
- [LeetCode] Open the Lock 开锁
You have a lock in front of you with 4 circular wheels. Each wheel has 10 slots: '0', '1', '2', '3', ...
- Python的基础学习(第二周)
模块初始 sys模块 import sys sys.path #打印环境变量 sys.argv#打印该文件路径 #注意:该文件名字不能跟导入模块名字相同 os模块 import os cmd_res ...
- [Codeforces 922E]Birds
Description 题库链接 一条直线上有 \(n\) 棵树,每棵树上有 \(c_i\) 只鸟,在一棵树底下召唤一只鸟的魔法代价是 \(cost_i\) 每召唤一只鸟,魔法上限会增加 \(B\) ...