#1.面向对象的相关概念
01 对象是什么?
什么都是对象,对象是具体的事物;
02 对象的描述信息(静态特征)
03 对象的行为特征(动态的行为)
04 js中的对象
对象的定义:键值对(key-value)的集合 | 属性(方法)的工具包|对变量和函数的封装;
对象的组成:
静态特征:属性 (定义在对象那个中的变量)
动态行为:方法 (定义在对象中的函数)
补充:面向对象和面向过程并没有孰优孰劣,解决问题的时候需要看实际情况(选择)
为什么要使用面向对象的方式来写代码?高效,方便,复用
#2.面向对象的三大特性
01 封装
02 继承
03 多态
(01)封装:
作用:方法代码的维护,提高代码的复用性,更安全的访问数据的方式,更有利于模块化编
注意:js中的封装多了一层意思,就是使用对象来封装变量和函数
(02)继承:
现实生活中的继承:继承遗产,一个人获得另一个人所拥有的财富或者资源的方式.
编程语言中的继承:一个类(对象)获得另一个类(对象)的属性和方法的一种方式.
面向对象的语言特征:类(c++)/java c语言是面向过程的语言(没有类)
js中没有类(class),支持面向对象的语言
(03)多态:
多种形态:
表现:
01:对于相同的操作,不同的对象表现出不同的行为.
02:隐藏不同
实现:js天生具备多态的特征(弱类型语言)
#3.创建对象的几种方法
(01)创建对象的几种方法
01 字面量方式
02 使用内置的构造函数
03 使用简单的工厂函数
04 自定义构造函数
05 Obeject.creat()
(02)字面量的方式
结构:
var 对象 = {
属性名01:属性值,
属性名02:属性值,
方法01:function (){函数体}
}
适用场合:只需要简单创建单个对象
问题:如果需要创建多个相似的对象,那么代码中的冗余度太高(重复的代码太多)
(03)使用内置函数创建对象
使用方法: new 构造函数
eg:创建对象
//1.创建一个空对象
var book1 = new Object();
//2.设置属性
book1.name = '花田半亩';
book1.author = '田维';
book1.price = '40.01';
//3.设置方法
book1.logDes = function (){
console.log('书名:' +this.name);
}
book1.logDes();
//创建多个对象
var book2 = new Object();
book2.name = '三国演义';
book2.author = '罗贯中';
book2.price = '34.01';
book2.logDes = function (){
console.log('书名:'+this.name);
}
console.log(book1);
console.log(book2);
(4)使用简单工厂函数创建对象
不足:对象类型判断的问题.(无法区分对象的类型)
eg:
//1.提供函数
function creatBook(){
//2.创建空的对象
var o = new Object();
//3设置属性和方法
o.name = '默认的名称';
o.author = '默认的作者';
o.logDes = function (){
console.log('作者是:' +this.author);
}
//4.返回新创建的对象
return o;
}
//5.创建对象
var book1 = creatBook();
var book2 = creatBook();
console.log(book1);
console.log(book2);
封装:把固定的部分写成函数的函数体,把变化的部分提取,作为参数传递
//01.提供函数
function creatBook(name,author){
//02.创建空对象
var o = new Object();
//03设置属性和方法
o.name = name;
o.author = author;
o.logDes = function (){
console.log('作者是:'+this.author);
}
//04返回新创建的对象
return o;
}
//05.创建对象
var book1 = creatBook('小学数学','教育部');
var book2 = creatBook('高等数学','燕子');
console.log(book1);
console.log(book2);
问题:
如果创建多个不同类型的对象,那么我们无法分辨
function creatPerson(name,age){
var o = new Object();
o.name = name;
o.age = age;
return o;
}
function creatDog(name,age){
var o = new Object();
o.name = name;
o.age = age;
return o;
}
//创建具体的对象
var obj1 = creatPerson('张三',88);
var obj2 = creatDog('物理',13);
console.log(obj1);
console.log(obj2);
//typeof 判断类型
console.log(typeof obj1);
console.log(typeof obj2);
console.log(obj1.constructor);
console.log(obj2.constructor);
(5)自定义构造函数的方式创建对象
术语:构造函数 == 普通函数,人为的区分(手写字母大写)
构造函数:主要做的是初始化的处理(设置属性和方法)
new : 创建对象 ({})
var obj = new Object();
核心过程: 01 提供一个构造函数(普通函数首字母大写)
02 通过this指针来设置对象的属性和方法
03 使用new 构造函数()创建对象
内部的实现过程:
01 提供构造函数
02 创造一个空的对象{} ===> Object
03 设置新创建对象的原型对象的属性和方法
04 设置新创建的对象的构造函数为当前的构造函数
05 把新创建的对象赋值给this
06 通过this设置属性和方法
07 默认在最后把新创建的对象返回
(01)自定义构造函数方式创建对象内部的实现细节:
01 我们在使用new关键字调用构造函数的时候,内部默认会创建一个空的对象
02 默认会把这个空的对象赋值给this
03 通过this来设置新对象的属性和方法
04 在构造函数的最后,默认会把新的创建的对象返回
(02)自定义构造函数和工厂函数的对比:
01 函数的名称不一样,构造函数首字母大写
02 自定义构造函数创建方式内部会自动的创建对象并且赋值给this
03 默认会自动返回新创建的对象
(03)返回值 :
01.没有显示的return ,默认会把新创建的对象返回
02.显示的执行了return语句.就得看具体情况
001 返回的是值类型,那么直接忽略该返回(把新创建的对象返回)
002 返回的是引用类型的数据,return 的对象会覆盖到掉新创建的对象,直接返回引用数据类型的值
(04)构造函数和普通函数有什么区别?
001 首字母大写
002 构造函数在调用的时候需要和new一起使用,普通函数直接调用
eg:
function Person(name,age) {
//01 创建对象{}
//var o = new Object();
//02 把新的对象赋值给this
//this = o;
//03 设置新创建对象的原型对象为构造函数的原型对象
//o.__proto__ = Person.prototype;
//04 设置新创建对象的构造函数为当前的构造函数
//o.constructor = Person;
this.name = name;
this.age = age;
this.showName = function () {
console.log(this.name);
}
//默认把新创建的对象返回
//return this;
}
var p1 = new Person("张三",99);
var p2 = new Person("李四",0.9);
p1.showName();
p2.showName();
(6)构造函数注意事项
(01)函数调用:
new:
创建对象,并在最后返回该对象
构造函数:用于初始化对象
一普通函数的方式来调用构造函数,那么内部的this值的向的是window
(02)Object是所有对象的基本对象
001 关键字 instanceOf:用来判断当前对象是否是某个类型的实例(检查某个对象是否是使用指定构造函数创建的)
语法: 对象 instanceOf 构造函数(类型)
002 构造函数本身是一个函数,在调用可以直接调用
(7)构造函数方式创建对象存在的问题
问题:
01 把函数写在外部,破坏了封装性。
02 增加一个全局变量。
03 构造函数必须要和new一起使用,如果直接调用那么无法创建对象
2.this 的指向
如果是使用new构造函数()调用 那么this -->具体的对象
如果是以普通函数的方式调用,那么this-->window
3.this的丢失问题
以普通函数的方式来调用函数这里的this-->window
(8)构造函数的原型对象
#4 构造函数的原型对象
#01 什么是原型对象?
在使用构造函数构造对象的时候,默认会生成一个与构造函数相关联的对象.默认情况下,该对象是一个空的对象({})
#02 原型对象的作用(特点)
1.使用函数的原型对象 上面的属性和方法 可以被使用该构造函数创建出来的所有对象 所共享
2.使用构造函数创建的对象,能够自动拥有(可以使用)原型对象中所有的属性和方法.
#03 如何访问原型对象
1.构造函数.prototype
2.对象.__proto__
3.Object.getPrototype(对象)
#04 原型对象的使用
1.可以像设置普通对象一样来利用对象的动态特性设置属性和方法
2.使用字面量的方法来设置原型对象(直接替换)
#05 约定(说法)
1.正确的说法:
该对象的构造函数的原型对象
构造函数的原型
构造函数的原型对象
对象的原型
以上四种说法,一世一样,都是该对象的构造函数的原型对象
补充: 设置原型对象的属性和方法的时候:构造函数.prototype.属性
对象.prototype.属性
(9)实例化和实例
实例化: 通过构造函数创建对象的过程,就成为实力化.
实例: 通过构造函数创建的对象被称为该构造函数的实例,一般再说实例的时候,需要指定构造函数,也就是说,我们通常会说这个对象是xxx构造函数的实例.
(10)替换原型对象的补充:
01 注意原型对象的(位置).建议 (在设置完原型对象之后,再统一的创建对象)
02 替换原型对象之后,需要修正构造器属性 coonstructor 指向的是创建当前对象的构造函数,对象本身并没有constructor属性,该属性是原型对象上面的.
(11)使用原型对象的注意事项
01 访问属性| 方法
访问逻辑:首先先在对象身上查找是否有对应的属性|方法,如果有就直接使用,如果没有那么就查找原型对象.
常用术语:
成员:属性 + 方法
实例成员:实例属性+ 实例方法
原型成员:原型对象的属性 + 原型对象的方法
02 设置属性 |方法
通过对象.属性的方式设置的是实例对象的属性
设置对象的时候.如果是引用类型的,对象.属性.属性是可以设置原型对象的;
###__proto__属性:
该属性不是一个标准的属性(ECMA5中没有),ES6中添加了这个属性
在代码中不要出现这个属性,这个属性一般用来调试的.
在之前,该属性是某些浏览器厂商提供(部分浏览器支持)
###hasOwnProperty属性
has Own Property 我自己是否有这个属性(只检查自己的成员)
in 关键字
01 遍历对象
02 判断对象是否存在指定的属性(实例成员 + 原型成员)
语法: '属性' in 对象
1.isPrototypeOf 是否是某个对象的原型对象
2.Object.getPrototypeOf(对象)