JS 构造函数与类
严格来说, JS 并不是一个面向对象的语言, 类似 Java, Python, C++ 这样的. JS 的独特精妙的设计其实是 原型 prototype
因此这里讲一嘴面向对象其实是为了后面引出原型的东西.
总之, JS 的面向对象 (封装, 继承, 多态) 并不真正存在, 但可以巧用 prototype
近似实现而已.
后来看作者自己说之所以搞这么一通主要也是为了靠近和迎合一下 Java 而已. 但 JavaScript 和 Java 除了名字有点像, 其他哪里都不像, 完全是两个领域的东西.
new 调用函数 4 步走
在 js 中函数的调用大致有好几种常见的, 如 函数声明调用, 匿名函数调用, 对象.方法调用, call 和 apply 调用. 而这里将要说的一种调用是通过 new
来调用函数.
new 函数()
注意这里的 new
和其他面向对象的语言不太一样, 并非是 new 一个对象这么简单哦, 但这里呢还是从规则和语法层面先了解再说吧, 它主要会进行 "四步走":
- 函数体内会自动创建一个空对象
{}
- 函数的上下文 (
this
) 会指向这个空对象 - 函数体内的语句会执行
- 函数会自动返回上下文
this
不论函数是否有return
function fn() {
this.a = 1
this.b = 2
}
var obj = new fn()
console.log(obj);
这里就用了 new 来调用函数, 咱们就仔细来分析一波这个过程吧.
// 第一步: 创建空对象
var obj = {}
// 第二步: this 指向这个空对象
this = obj
// 第三步: 函数体内的语句执行
obj = { a: 1, b: 2}
// 第四步: 函数自动返回 this
return this
因此上例 new 调用函数()
程序的执行结果就是返回一个对象, { a: 1, b: 2 }. 这个 new 来调用函数会自动返回一个对象, 且会执行一些逻辑就还是有点东西的哦.
构造函数
就是类创建时的一些自动调用的方法呀, 初始化啥的, 即 Java 类里面的同类名一致的方法实现, 或者是 Python 类里面的 def __ init __
它的内部语句会给刚创建的对象 (实例化) 添加若干属性和方法, 助力其完成对象的初始化.
在 JS 中构造函数必须要通过 new
进行调用, 开发者们也约定构造函数命名时首字母要大写.
当然咱不遵守约定就小写也是行的, 只是有点不讲武德而已.
function People(name, age, sex) {
this.name = name
this.age = age
this.sex = sex
}
var youge = new People('油哥', 28, '男')
var yaya = new People('亚亚', 18, '女')
- 构造函数的关键在于
new
关键字调用, 而非是否函数首字母大小写 - 构造函数中的
this
指向实例对象而非函数本身
接着尝试给对象添加一下方法看看:
function People(name, age, sex) {
this.name = name
this.age = age
this.sex = sex
this.sayHi = function () {
console.log('我是: ', this.name, '今年: ', this.age, '岁啦!');
}
}
var youge = new People('油哥', 28, '男')
var yaya = new People('亚亚', 18, '女')
youge.sayHi()
yaya.sayHi()
PS C:\Users\Administrator\Desktop> node test.js
我是: 油哥 今年: 28 岁啦!
我是: 亚亚 今年: 18 岁啦!
类与实例
上面所谈的关于 JS 中通过构造函数便基本实现了面向对象的一些核心要素. 比如在写构造函数 People
时, 我们用的核心思想是 抽象
. 然后再通过 new 函数()
的四步走时, 创建了新对象, 添加了一些属性和方法, 则实现了 封装
和进行实例化.
计算机其实就是对现实世界的抽象. 里面的类和实例也对应着现实世界中的 "归类 和 个体".
从编程语言来看呢, Java, C++, Python 是面向对象的 OO 语言, 而 JavaScript 是基于对象 object-based
的语言. JS 中的构造函数可以类比于面向对象里面的 class
. 但二者的实现逻辑是完全不同的. JS 的独特之处是基于原型 prototype
的设计哦.
当然在 ES6
以后 JS 也引入了一个 class
的关键字 和构造函数 constructor
来模拟纯面向对象语言的特性, 如继承. 但本质上还是基于原型链来展开的.
关于构造函数和类的简单认知就差不多了, 核心还是为了引出 JS 原型 这个有点牛的东西.