前言

在 ES6 规范中,引入了 class 的概念。使得 JS 开发者终于告别了,直接使用原型对象模仿面向对象中的类和类继承时代。

但是JS 中并没有一个真正的 class 原始类型, class 仅仅只是对原型对象运用语法糖。所以,只有理解如何使用原型对象实现类和类继承,才能真正地用好 class

类语法不会为JavaScript引入新的面向对象的继承模型。

class类概念与语法

ES5之前不存在类的概念,创建对象使用的构造函数,通过new操作符来创建;

为使JS更像面向对象,ES6版本引入class概念,其基本语法:

class Cat{constructor(name,age){this.name = name;this.age = age;}Say(){return '我的名字是' + this.name;}
}
var cat1 = new Cat('有鱼',2);
console.log(cat1.Say());//我的名字是有鱼

原型链图示

代码解析:

① constructor是一个构造函数方法,创建对象时自动调用该方法

② constructor是默认存在的,可以省略,程序亦可以调用

③ this指的是实例化对象

④类中声明的方法不能加function关键字

⑤方法之间不要用逗号分隔,否则会报错

二、class类与原型的关系

class类本质上就是一个函数,自身指向的就是构造函数,看代码:

console.log(typeof Cat);// function
console.log(Cat.prototype.constructor ===Cat);//true

class类是构造函数的另一种写法,仍然存在prototype方法

console.log(Cat.prototype);//object

可以通过原型prototype修改类方法和新增方法

Cat.prototype.Say = function(){return return '我的名字是' + this.name+',我是原型prototype声明同样的Say方法,把原有Say方法覆盖了';
}
cat2 = new Cat('年年',5);
console.log(cat2.Say());//我的名字是年年,我是原型prototype声明同样的Say方法,把原有Say方法覆盖了
Cat.prototype.Go = function(){return return '我的年龄是' + this.age;
}
console.log(cat2.Go());//我的年龄是5

还可以通过Object.assign方法来为对象动态增加方法

Object.assign(Cat.prototype,{Eat:function(){return this.name;},Run:function(){return this.age;}
})
cat3 =new Cat('卡卡',4);
console.log(cat3.Eat());//卡卡
console.log(cat3.Run());//4

也可以使用实例对象的__proto__属性新增类的方法

cat3 =new Cat('卡卡',4);
cat4 =new Cat('楼楼',10);
cat3.__proto__.Play = function(){return this.name;
}
console.log(cat3.Play());// 卡卡
console.log(cat4.Play());// 楼楼

实例属性和原型属性

实例属性:constructor里面的属性为实例属性,即定义在this对象上

原型属性:除去实例属性都称为原型属性,即定义在class类上

hasOwnProperty方法:可以通过hasOwnProperty()方法进行判断属性是否是实例属性

in操作符:能够访问到属性时返回true,无论是实例属性还是原型属性

class Person(){constructor(per1,per2){this.per1 = per1;this.per2 = per2;}Say(){return per1+per2;}
}
var box=new Person('年年','有鱼');
console.log(Person.hasOwnProperty("per1"));//true
console.log(Person.hasOwnProperty("per2"));//true
console.log(Person.hasOwnProperty("Say"));//false
console.log("per1" in Person);//true
console.log("per2" in Person);//true
console.log("Say" in Person);//true
console.log("Go" in Person);//false

class类的继承

通过extends关键字实现类的继承

class Person{constructor(name,age){this.name = name;this.age = age;}getName(){return this.name;}getAge(){return this.age; }
}
class Student extends Person{getName(){return '我覆盖了父级的方法,'+ this.name;}getScore(){return '我是子级新增的方法,'+this.name;}
}
var stu1 = new Student('有鱼',2);
console.log(sut1.getName());// 我覆盖了父级的方法,有鱼
console.log(sut1.getAge());//2
console.log(sut1.getScore());// 我是子级新增的方法,有鱼

通过super关键字进行拓展父类构造器或方法

super作用:

①子类使用构造器constructor的时候,必须使用super关键字,用来扩展构造器

②子类同名方法会覆盖父类同名方法,使用super关键字后则可以调用到父类的同名函数

class Person{constructor(name){this.name = name;}getName(){console.log('我是父级类getName方法输出来的');}getAge(){console.log(this.age); }
}
class Student extends Person{constructor(name,age,sex){super();//必须先调用super,才能使用constructor,才能使用this对象this.name = name;this.age = age;this.sex = sex;}getName(){super.getName();//调用super,才能调用父类同名函数getNameconsole.log('我是子级类getName方法输出来的');}
}
var stu1 = new Student('有鱼',2);
stu1.getName();
// 我是父级类getName方法输出来的
// 我是子级类getName方法输出来的

static关键字的使用

①static关键字是类的方法

②只能通过类名来调用,不能被实例对象调用

③static方法也可以被继承

class Person{constructor(name,age){this.name = name;this.age = age;}static getAge(){console.log('我是静态属性static');}
}
class Student extends Person{}
var stu1 = new Student('有鱼',2);
Person.getAge();//我是静态属性static
Student.getAge();//我是静态属性static
stu1.getAge();//stu1.getAge is not a function

待优化

ES6:class

通过类来创建对象,使得开发者不必写重复的代码,以达到代码复用的目的。它基于的逻辑是,两个或多个对象的结构功能类似,可以抽象出一个模板,依照模板复制出多个相似的对象。就像自行车制造商一遍一遍地复用相同的蓝图来制造大量的自行车。

使用 ES6 中的 class 声明一个类,是非常简单的事。它的语法如下:

class Person {constructor(name){this.name = name}hello(){console.log('Hello, my name is ' + this.name + '.');}
}var xiaoMing = new Person('xiaoMing');
xiaoMing.hello() // Hello, my name is xiaoMing.

xiaoMing 是通过类 Person 实例化出来的对象。对象 xiaoMing 是按照类 Person 这个模板,实例化出来的对象。实例化出来的对象拥有类预先订制好的结构和功能。

ES6 的语法很简单,但是在实例化的背后,究竟是什么在起作用呢?

class 实例化的背后原理

使用 class 的语法,让开发者告别了使用 prototype 模仿面向对象的时代。但是,class 并不是 ES6 引入的全新概念,它的原理依旧是原型继承。

typeof class == "function"

通过类型判断,我们可以得知,class 的并不是什么全新的数据类型,它实际只是 function (或者说 object)。

class Person {// ...
}typeof Person // function

Person 的属性并不多,除去用 [[...]] 包起来的内置属性外,大部分属性根据名字就能明白它的作用。需要我们重点关注的是 prototype__proto__ 两个属性。

(关于 __proto__ 可以在本文的姊妹篇 找到答案)

实例化的原理: prototype

先来讲讲 prototype 属性,它指向一个特殊性对象:原型对象

原型对象所以特殊,是因为它拥有一个普通对象没有的能力:将它的属性共享给其他对象。

在 ES6 规范 中,对 原型对象 是如下定义的:

object that provides shared properties for other objects

原型对象是如何将它的属性分享给其他对象的呢?

这里使用 ES5 创建一个类,并将它实例化,来看看它的实质。

function Person() {this.name = name
}// 1. 首先给 Person.prototype 原型对象添加了 describe 方法 。
Person.prototype.describe = function(){console.log('Hello, my name is ' + this.name + '.');
}// 2. 实例化对象的 __proto__ 指向 Person.prototype
var jane = new Person('jane');
jane.__proto__ === Person.prototype;// 3. 读取 describe 方法时,实际会沿着原型链查找到 Person.prototype 原型对象上。
jane.describe() // Hello, my name is jane.

人类身份验证 - SegmentFault

类​developer.mozilla.org

人类身份验证 - SegmentFault​segmentfault.comJavascript定义类(class)的三种方法 - 阮一峰的网络日志​www.ruanyifeng.com

- 掘金​juejin.im- 掘金​juejin.im

中getname_浅析JS中的class相关推荐

  1. php中base64和js中base64可互相加解密

    php中base64和js中base64可互相加解密 前提:加解密的字符必须转换成UTF-8编码格式. php代码: <?php $str='中国航母辽宁号-歼15战机GOOD=ok'; ech ...

  2. python变量存储 堆与栈内存内存_浅析JS中的堆内存与栈内存

    最近跟着组里的大佬面试碰到这么一个问题, Q:说说var.let.const的区别 A:balabalabalabla... Q:const定义的值能改么? A:你逗我?不能吧 不知道各位看官怎么想? ...

  3. uniapp 获取到js文件var一个变量怎么获取到这个变量值_浅析Js中const,let,var的区别及作用域...

    理解:let变量的作用域只能在当前函数中 js中const,let,var的区别及作用域_lianzhang861的博客-CSDN博客​blog.csdn.net 全局作用域中,用 const 和 l ...

  4. java js中 function函数报错_浅析JS中对函数function的理解(基础篇)

    正文:我们知道,在js中,函数实际上是一个对象,每个函数都是Function类型的实例,并且都与其他引用类型一样具有属性和方法.因此,函数名实际上是指向函数对象的指针,不与某个函数绑定.在常见的两种定 ...

  5. 浅析Js中${}字符串拼接

    字符串拼接 Es6中的${}新语法 这是es6中新增的字符串方法 配合反单引号完成拼接字符串的功能 反单引号怎么打出来? 将输入法调整为英文输入法,单击键盘上数字键1左边的按键. 用法: step1: ...

  6. 计算机网络中路由器,浅析计算机网络中的路由器

    浅析计算机网络中的路由器 通过路由器的结构 ,分析了路由器的基本原理及功能 ,进而 (本文共2页) 阅读全文>> 由于路由器的应用越来越广泛,所以对网络路由器在使用过程中发生的故障,我们也 ...

  7. SQLAlchemy中模糊查询;JS中POST带参数跳转;JS获取url参数

    SQLAlchemy中模糊查询,如何like多个关键字 JS中POST带参数跳转 一个项目中要跳转到另外一个项目,还需要带参数 考虑到安全性的问题,最好是用POST跳转,不能再URL中拼参 所以找到了 ...

  8. js在html中拆分字符串,js中的split方法 js用split()取字符串

    本来想通过静态HTML传递参数,动态读取url0和url字段,试了一下没成功.定义和用法 split() 方法用于把一个字符串分割成字符串数组. 语法 stringObject.split(separ ...

  9. JQuery中width和JS中JS中关于clientWidth offsetWidth scrollWidth 等的含义

    JQuery中: 1.width()方法用于获得元素内容所占的宽度: 2.innerWidth()方法用于获得包括内边界(padding)的元素宽度: 算式:innerWidth()=width()+ ...

最新文章

  1. PaaS模式创新:实现应用可移植性
  2. 压力管道流量计算公式_带你全面了解各种流量计!
  3. 企业运维之域控篇(十)--SERVER 2003 迁移到 SERVER 2008 (异机)
  4. php for循环in的用法,JavaScript中for in循环是如何使用的?需要注意些什么?
  5. Javaweb学习笔记——(二十二)——————文件上传、下载、Javamail
  6. “城迷”:黑白梦与精神逃离
  7. 你知道304吗?图解强缓存和协商缓存
  8. PHP苹果不给上架,苹果商城上架拒绝
  9. 软件行业选择大公司还是小公司
  10. MySQL循环结构例题_Mysql:循环结构
  11. ASP.NET中DropDownList控件的简单使用--DDL绑定数据库表中值,选择DDL中值直接检索数据...
  12. System.Data.SqlClient.SqlException: 用户'opper\ASPNET' 登录失败的解决办法!
  13. 煮酒论英雄——点评三国人物
  14. 架构设计第三步:评估和选择备选方案
  15. 全志系列芯片选型简介
  16. 今天,我和C开始交往了
  17. 颜色的前世今生15·CMYK系统(原色的选择)
  18. etl工程师 面试题_关于数据仓库工程师的一般面试题目
  19. web前端学习(CSS篇)
  20. 利用OGR处理几何要素

热门文章

  1. ZOJ-3704 I am Nexus Master! 模拟
  2. 小凡Linux国产网游《时空浩劫》安装+体验
  3. Oracle 客户端工具
  4. NUMA与英特尔下一代Xeon处理器学习心得(4)
  5. GridView里的一点小功能:截取多余字符、改变鼠标经过行的样式
  6. mysql如何保证高可用_mysql怎么保证高可用
  7. 二叉树输出(信息学奥赛一本通-T1366)
  8. 鱼塘钓鱼(信息学奥赛一本通-T1373)
  9. 信息学奥赛一本通C++语言——1078:求分数序列和
  10. 3 FI配置-企业结构-分配-给公司分配公司代码