面向对象

66 阅读7分钟

任何数据都有两种定义方式:

1.字面量方式 - 定义好以后一眼就能看透

字面量方式,就是直接定义,让我们可以一目了然的看出,这个数据的类型。例如:

var num = 10
var str = 'abcdef'
var bool = true
...

2.构造函数方式 new XXX 构造一个对象 - 任意数据都可以是对象

   var arr = new Array()
   var obj = new Object()
   var num = new Number()
   var str = new String()
   ...

这种通过new的方式来定义对象的方式,就叫做构造函数方式。

这种方式定义的数据,也是可以像字面量方式定义的数据一样,进行数学运算、字符串拼接等操作的。例:

```
var num = new Number(10)
num += 5
console.log(num) // 15var str = new String('abcd')
str += 'ef'
console.log(str) // 'abcdef'
```

这也就造成了,在js中,对象是无所不能的,无

例如:字符串有方法,数字也有方法

 字符串.startsWith()
 数字.toFixed()
 let fn = function() {}
 console.log(fn);
 console.dir(fn)

二、面向对象

1、介绍

面向:脸面朝向

对象:js的重要组成部分

连在一起,就是脸面要朝向对象,也就是要重视对象。

面向对象是一种更加注重对象编程思想,是一种超脱的、高级的编程思想。

用专业术语来讲,面向对象又叫做OOP(Object Oriented Programming)

我们之前的编程思想叫做面向过程编程思想POP(Procedure Oriented Programming)。

2.比较

面向对象并不是一种新的语法

面向对象是一种高级的编程思想

我们平常所使用的编程思想不是对象,是面向过程

我们之前编程的思想更加注重过程,没有更加注重对象

3、创建对象

既然要面向对象,更加注重对象,就要先明白如何创建对象是最好的方式,如何给对象添加属性和方法才是最好的方式。

直接创建:

var obj = {}

构造函数方式创建:

var obj = new Object();

Object是一个系统提供的构造函数,这个构造函数专门用来创建对象使用的。 如下:保存多个人的信息,需要这样创建多次。

var obj1 = {
    name: '张三',
    age: 12,
    sex: '男'
}
​
var obj2 = {
    name: '李四',
    age: 13,
    sex: '女'
}
​
var obj3 = {
    name: '王五',
    age: 11,
    sex: '女'
}
。。。

从上面的代码可以看出来,每次创建对象都是在重复动作

这时候,应该用函数来处理重复动作

4.面向对象有三大特点:

1.封装性 - 对象

2.继承性

3.多态性

4、工厂函数

定义一个函数,每次调用都能得到一个对象

function createObj(name,age,sex){
    var obj = {
        name,
        age,
        sex
    }
    return obj;
}
var obj1 = createObj("张三",12,"男");
var obj2 = createObj("李四",13,"女");
var obj3 = createObj("王五",11,"女");

这种调用就能创建对象的函数,叫做工厂函数。创建出来的每个对象的结构一致,如:电商网站中的商品对象。

优点:可以同时创建多个对象

缺点:输出后无法立马看出对象的类别;创建出来的没有具体的类型(比如是Array和Number),都是object类型的,但我们看到自己的对象只是object,不知道具体是什么类型。

代码:

function factory(name,age){
    var obj = new Object();
    obj.naem = name;
    obj.age = age;
    return obj;
}
var zs = factory("张三",12);
var ls = factory("李四",20);
console.log(zs);
console.log(ls);

效果:

1701.png

函数解决重复

// function createObj(name, gender, age) {
//     let obj = {
//         name: name,
//         gender: gender,
//         age: age
//     }
//     return obj
// }
// 使用对象创建对象
// let wc = createObj('汪晨', '男', 11)
// let xl = createObj('胡小龙', '男', 12)
// let zsl = createObj('张胜澜', '女', 18)

5、构造函数

构造函数:专门用来创建对象的函数

语法:

new 函数() - 返回一个对象

从使用构造函数方式来看数字类型、字符串类型。。。

当我们定义好不同的数据,从外观上就能看出,这个数据的具体类型,例:

var arr = new Array();
var obj = new Number();
var str = new String();
console.log(arr);
console.log(obj);
console.log(str);

输出结果:

1702.png 这种专门用于new来创建对象的函数,叫做构造函数。

Number、String这种函数,除了可以用new创建对象外,还可以进行类型转换。

其实这样用new创建对象的函数,我们自定义的函数也是可以的:

function fn() {}
var f = new fn()
console.log(f)

图示:

1703.png 每个函数都可以这样做。当一个函数被用new来创建对象的时候,这个函数就叫做构造函数了。

通过上面代码,我们发现,如果使用自己定义的函数来创建对象的话,就可以立马看到这个对象的具体类型了。

所以,解决工厂函数的问题,就可以使用自定义的构造函数来实现。

例:

function Person(){
   
}
var zs = new Person();
function fn(){
​
}
var ls = new fn();
console.log(zs);
console.log(ls);

输出结果:

1704.png

6、自定义构造函数

function Person(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
}
var obj1 = new Person("张三",12,"男");
var obj1 = new Person("李四",13,"女");
var obj1 = new Person("王五",11,"女");

这时候,我们会奇怪,因为函数并没有被对象调用,那this指的是谁?函数并没有返回值,得到的是什么?

构造函数和普通函数不同的地方在于使用new的时候,中间发生了很多看不见的过程:

  1. 创建了一个新对象
  2. this指向了这个新对象
  3. 执行构造函数中的代码,给对象添加属性和方法
  4. 返回这个新对象

使用new构造函数来创建对象的过程称之为实例化

构造函数注意事项:

  1. 构造函数天生就是用来创建对象的,所以必须和new配合使用,否则就不具备创建对象的能力
  2. 构造函数内部不能有return关键字,因为构造函数会自动返回对象。如果返回基本数据类型,和不加效果一样,如果返回复杂数据类型,构造函数就没意义了。
  3. 如果new的时候,不需要参数,那么小括号可以省略
  4. 人们通常将构造函数的首字母大写

此时的构造函数有个缺点:

从一个构造函数中创建出的对象,实现的是同一种功能,他们拥有的方法应该是一样的,也就是说,同一个构造函数中new实例化得到对象,应该具备同样的方法。

例:

function Person(name){
    this.name = name;
    this.say=function(){
        console.log("说话");
    }
}
var obj1 = new Person("张三");
var obj2 = new Person("李四");
console.log(obj1.say == obj2.say); // false  表示这是两个空间

通过比较发现,方法是不一样的。造成了内存浪费。

// 自定义构造函数
// function fn() {}
// let f = new fn()
// console.log(f);

// function person() {}
// let p = new person()
// console.log(p);

// 可以使用自定义构造函数解决工厂函数的缺点
// 自定义构造函数的时候有几个注意事项:
/*
1.约定成俗 构造函数的首字母通常都是大写的
2.在new他的时候,如果不需要传递参数,就可以省略小括号
3.构造函数也是函数,也能当做普通函数去调用它
*/
// function Person(){}
// let p1 = new Person()
// console.log(p1);

// let p2 = new Person
// console.log(p2);

// function Man() {
//     console.log(666);
// }
// let m = new Man
// console.log(m);
// Man()

总结:

1.new操作符到底干了什么?
2.this在构造函数中代表new出来的对象
全局
普通函数
事件函数
自调用函数
定时器函数
对象方法
箭头函数

7、原型

7.1、原型概念

任何一个对象提升自带一个属性:__proto__,这个属性对应的值是一个对象,这个对象叫做对象的原型,或叫做对象的原型对象。

var obj = {}
console.log(obj)

效果:

1705.png

7.2、原型作用

原型中的属性和方法,默认就能被对象所访问。

var arr = []
console.log(arr)

图示:

1706.png

关系介绍

<script>
function Person(name) {
    this.name = name
}

let p1 = new Person('p1')
let p2 = new Person('p2')
console.log(p1, p2);

// 测试p1和p2是否拥有同一个原型
// console.log( p1.__proto__ === p2.__proto__ ); // true

// 构造函数比作 母    
// new出来的对象比作  子
// 原型比作  父

// 构造函数和原型之间的关系
console.dir(Person)
// 比较构造函数的prototype和原型是否是同一个
console.log( p1.__proto__ === Person.prototype ) // true
// 函数会天生自带属性prototype,指的是原型
// 原型天生自带属性constructor,指的是构造函数
</script>

效果:

1707.png

面向对象写tab切换

面向对象书写步骤:

1.定义空构造函数 - 定义对象,调用方法实现效果,调用方法,就需要给原型上添加对应的方法

2.new构造函数的时候需要添加参数 - 通常是效果中最大标签选择器 - 添加形参

3.在构造函数中将所有需要操作的标签作为对象的属性

4.将事件放在init方法中