乐趣区

谈一谈javascript面向对象

从今天起我们开始讨论 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 语言精粹》(修订版)
原文链接

退出移动版