思考,输出,沉淀。用通俗的语言陈述技术,让自己和他人都有所收获。
作者:毅航😜
前言
如果你接触过C++、Java
这类编程语言的话,一定对其中的面向对象
语言特性有比较深刻的认识。 而当你接触过这些语言后,再接触JavaScript
时,你可能会觉得JavaScript
中有关对象
总是有些奇怪。不知你是否考虑过这样一个问题,即当我们在JavaScript
谈论对象
时,这个对象
究竟指的什么呢?
究竟什么是面向对象
我相信,不同人对于面向对象
可能有着不同的看法。从笔者
角度来看面向对象
中所提及的对象
其实可以理解为对现实世界的抽象。以现实世界的牛、羊
来举例,当我们谈及牛、羊
时你脑海中大概率会快速浮现出牛、羊
的大体样貌,为什么我们脑海中会立即形成这样的画面呢?很简单,因为通过日常的学习、观察我们已经潜移默化的记住了牛、羊
的显著特征
,而这些其所具有的特征
,在编程的世界中有另外一个名词------属性
。进一步,牛、羊
通常都具有基本活动能力,例如,牛
会发哞
的叫声,而羊
则会发出咩
的叫声,因此在计算机
世界中,我们通常通过行为
来刻画事物所独有的特点。
通过上述分析,不难发现,面向对象
中的对象
并不是凭空而来的一个名词,其切实的反映了我们对于这个世界的认识。简而言之,面向对象
就是在程序中通过数据和行为来刻画现实世界的事物,并以对象
为基本单位来刻画现实世界中各个实体的交互。
JavaScript
中的对象
经过之前对于面向对象
的解释,相信你对于面向对象
已经有了基本的认识。在像C++、Java
这类语言中,通常会使用类
的方式来描述对象,进而延伸出面向对象
中封装、继承、多态
的三大特性。
而在JavaScript
创立之初,其在某种程度上模仿Java
进行设计。比如,其内部也包含有new,this
等关键字。但是其也保留了一些自己特色,其可通过原型
来替代extends
关键字,进而来实现面向对象中继承
的特性。
其实熟悉JavaScript
的读者一定知道,JavaScript
中常用到的对象
通常有如下三种:
- Object(对象) :
Object
是JavaScript
中其他对象的基础。这一点类似于Java
中的Object
。 - Array(数组) :
Array
对象用于存储和操作有序的数据集合,它具有各种方法用于添加、删除
和操作数组元素。 - Function(函数) :函数被认为是可以用来调用执行的代码块。将函数视为
对象
一定程度上来爱看可以认为是JavaScript
所特有的。更进一步,在JavaScript
中函数
可以作为一等公民在JavaScript
中进行传递和存储。
此时,可能你会有这样的疑惑。那便是当在JavaScript
谈及的对象
时,这个对象
究竟在指什么。 在此先来说笔者
的一个结论,从笔者
视角来看,我认为可以将JavaScript
中的对象理解为由一组由属性和值构成的集合。换言之,在JavaScript
中你可以将对象
理解为多个key-value
对构成的集合。
例如,在如下这段代码中,其构建了一个User
对象,并动态指定了user
有两个属性:name
和age
。同时,还指定了一个sayHello
方法。
javaScript
const user = new Object();
// 动态添加属性
user.name = "YiHang";
user.age = "18"
// 动态添加方法
user.sayHello = function() {
console.log("sayHello");
};
// 调用方法
user.sayHello();
通过观察不难发现,你可以通过赋值
操作来完善化你的user
对象。这个赋值
操作不单单仅有变量,更有函数。而这些东西所表现出来的形式其实有点像key-value
的形式。至此,相信你大概率理解了笔者
之前所说的JavaScript
中对象的核心就是由一组组属性和值组成的集合。
当理解了上述这段话后,再结合之前我们对于面向对象
的介绍。你会发现在 JavaScript
中,我们之前谈及的属性
和行为
其实都被抽象为属性。同时, JavaScript
允许使用者在运行时动态的为对象
添改、删除属性,这使得JavaScript
具有动态性
这一特征。而c++、Java
是完全不具有这样特点的,其通常以类
为模板来构建对象,而类
在运行期间是不允许动态修改的!
函数也是对象
在此我们再来谈一谈 JavaScript
中的函数。不同于C++,Java
,在JavaScript
中函数也是一种特殊的对象,它同样可以拥有属性
和值
,而函数
和普通对象
的区别在于函数可以被调用。
我们先来看一段 JavaScript
代码
javaScript
function sayHello(){
var test = 1
}
sayHello.msg = "Hello JavaScript"
console.log(sayHello.msg)
在这段代码中,我们定义了一个函数 sayHello
方法。同时,在上述代码中,我们给 sayHello
函数设置了msg
的属性。当然,你也可以通过sayHello()
的形式来调用方法。进一步,因为函数是一种特殊的对象,所以在JavaScript
中,函数可以赋值给一个变量,也可以作为函数的参数,还可以作为函数的返回值。
怎么样,这样来理解函数可以复制给一个变量是不是有一种豁然开朗的感觉?以此为基础,我们再来看如下这段代码:
javaScript
function out(){
var num = 1
function inner(){
num++
console.log(number)
}
return inner
}
var inner = out()
inner()
观察上段代码可以看到,我们在 out
函数中定义了一个新的inner
函数,并且inner
函数引用了out
函数中的变量 num
,当调用 out
函数的时候,它会返回inner
函数。这种复杂的逻辑
在JavaScript
中称为闭包
!
(注:闭包
的有关知识后续可能会分析,敬请期待~)
总结
众所周知,在ES6
中JavaScript
开始引入的class
语法,进而可以通过一种更简洁、更清晰地定义对象和构造函数的方式。这种方式也使得JavaScript
在语法功能上更类似C++,Java
。
ES6
后的class
语法
javascript
// ES5构造函数
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function() {
console.log('Hello, ' + this.name);
};
// ES6 class
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, ${this.name}`);
}
总之,在笔者
看来,JavaScript
中谈论的对象和C++,Java
中谈论的对象有着很大的不同,JavaScript
中谈论的对象其实更像是:一组组由属性和值构成的集合。
当然可能我的理解也可能有些偏颇,欢迎在评论区理性讨论和交流指正。当然,如果觉得文章有帮助,不妨点赞+收藏,方便后期回顾总结。