从本日起我们最先议论javascript的面向对象
面向对象观点明白
面向对象言语有个标志=>它们都具有类的观点,经由历程类能够建立恣意多个具有雷同属性和要领的对象。
面向对象有三大特征
- 封装
- 继承
- 多态
但JS中对象与纯面向对象言语中的对象是差别的
JS中的对象:
无序属性的鸠合,其属性能够包括基础值、对象或许函数。
能够简朴明白为JS的对象是一组无序的值,个中的属性或要领都有一个名字,依据这个名字能够接见相映照的值(值能够是基础值/对象/要领)。
建立对象的基础要领
我们前面在讲原型链的时刻说过,两种建立对象的要领
对象字面量(对象直接量)
这是最快的
一个🌰:
const hero = {
name:"欧阳锋",
nickname:"西毒",
doSth:function(){
console.log('灵蛇杖法');
}
⚠️建立对象的属性名并不强迫运用引号包裹,除了以下几种状况
- 属性名中包括空格
- 属性名中包括连字符(中划线)
- 属性名中包括保留字
const obj={
"go home":"包括了空格",
"go-home":"包括了连字符",
"for":"这是保留字"
}
new 实例化一个对象
经由历程new运算符建立并实例化一个新对象,new背面是一个组织函数
const hero = new Object()
hero.name = "欧阳锋"
hero.nickname = "西毒"
hero.doSth = function () {
console.log('灵蛇杖法');
}
两种建立要领是一样的
建立对象经由历程以上两种体式格局好像足够了,然则当场景轻微庞杂一点,题目就显现出来了
当我门建立许多构造雷同的对象时,会发生大批的反复代码,为了处理这个题目,涌现了一个处理方案
工场形式
工场形式笼统了建立详细对象的历程,由于javascript没法建立类,开发人员就发清楚明了一种函数,用函数来封装以特定接口建立对象
一个🌰:
function createHero(name,nickname,doSth) {
const obj = new Object()
obj.name=name
obj.nickname=nickname
obj.doSth = function () {
console.log(doSth);
}
return obj
}
const hero1 = createHero("欧阳锋","西毒","灵蛇杖法")
const hero2 = createHero("黄药师","东邪","碧浪潮生曲")
console.log(hero1)
看下输出:
hero1和hero2都直接继承自Object实例,工场形式就是像工场一样来建立对象,建立的每个对象都是经由历程new Object()来建立的
厥后,开发人员有发现了更好的形式
组织函数形式
我们之前议论过,经由历程运用自定义组织函数来实例化对象
function Hero(name, nickname, doSth) {
this.name = name
this.nickname = nickname
this.doSth = function () {
console.log(doSth);
}
}
const hero3 = new Hero("欧阳锋","西毒","灵蛇杖法")
const hero4 = new Hero("黄药师","东邪","碧浪潮生曲")
console.log(hero3);
注重⚠️:建立自定义组织函数,函数名首字母大写,用来和非组织函数举行辨别
我们继承看下输出:
hero3是经由历程Hero实例化出来的,所以hero3先继承自Hero
要建立Hero的新实例,必需运用new操作符,以这类体式格局挪用组织函数现实上会阅历以下四个步骤,
- 建立一个新对象
- 将组织函数的作用域赋给新对象(因而this就指向了这个新对象)
- 实行组织函数中的代码(为这个新对象增加属性)
- 返回新对象
hero3和hero4都是Hero的实例,同时也是Object的实例
instanceof用于推断一个变量是不是某个对象的实例
console.log(hero3 instanceof Hero);//=>true
console.log(hero3 instanceof Object);//=>true
console.log(hero4 instanceof Hero);//=>true
console.log(hero4 instanceof Object);//=>true
属性和要领(公有&私有)
👆的🌰中,我们将属性和要领绑定在了组织函数Hero中的this上,hero3和hero4都能够接见这些属性
绑定在this上的属性我们称之为公有属性
绑定在this上的要领我们称之为公有要领
也就是说经由历程组织函数Hero实例化出来的对象是能够方位公有属性和公有要领的
既然有公有属性和公有要领,就肯定会有私有属性和私有要领
我们做一下调解
function Hero(name, nickname, doSth) {
let test = "私有属性"
function method(){console.log("私有要领");}
this.name = name
this.nickname = nickname
this.doSth = function () {
console.log(doSth);
}
}
const hero3 = new Hero("欧阳锋","西毒","灵蛇杖法")
const hero4 = new Hero("黄药师","东邪","碧浪潮生曲")
console.log(hero3);
看下输出:
在hero3中是不存在组织函数的私有属性和私有要领的
假如我们这建立完组织函数后,追加一下属性和要领,会怎样呢?碰运气
function Hero(name, nickname, doSth) {
let test = "私有属性"
function method(){console.log("私有要领");}
this.name = name
this.nickname = nickname
this.doSth = function () {
console.log(doSth);
}
}
Hero.localAttr="测试属性"
Hero.localMethod=function(){
console.log('测试要领');
}
Hero.prototype.proAttr="原型属性"
Hero.prototype.proMethod=function(){
console.log('原型要领');
}
const hero3 = new Hero("欧阳锋","西毒","灵蛇杖法")
const hero4 = new Hero("黄药师","东邪","碧浪潮生曲")
console.log(hero3);
console.log('localAttr测试属性:',hero3.localAttr);
console.log("localMethod测试要领:",hero3.localMethod);
console.log("proAttr原型属性:",hero3.proAttr);
console.log("proMethod原型要领:",hero3.proMethod);
看输出:
建立完实例对象后,
经由历程.运算符增加的属性是类静态公有属性(实例化的对象没法接见)
经由历程.运算符增加的要领是类静态公有要领(实例化的对象没法接见)
经由历程原型链增加的属性是公有属性(实例化的对象能够接见)
经由历程原型链增加的要领是公有要领(实例化的对象能够接见)
本日就到这里,来日诰日不见不散
收集整理了一套js进阶教程,民众号背景复兴“js进阶”即可领取
参考文献:
《javascript高等程序设想》(第三版)
《javascript设想形式》
《javascript言语精炼》(修订版)