面向对象
编程思想
1、面向过程:面向过程思想强调的是步骤,当碰见问题时,思考的是“我该怎么做”,分析出解决问题所需的步骤,一步步的去实现。
2、面向对象:面向对象思想强调的是对象,当碰见问题时,思考的是“我该让谁来做”。这个“谁”其实就是对象。找合适的对象做合适的事情。而对象如何去做(采用什么样的步骤)我们就不关心了,最终把问题解决掉就可以了。
面向过程是动作的执行者,面向对象是动作的指挥者
相关概念:
var 对象 = {
key1: value1,
key2: value2,
...
}
1、对象:无序的名值对
2、对象组成:
- 1、属性:对象的特征描述,静态,名词(不是函数的就是属性)
- 2、方法:对象的行为,动态(函数就是方法)
3、对象的基本特征:封装、继承、多态(了解)
4、类和实例
- 类:类是对象的类型模板
- 实例:实例是根据类创建的对象
- 面向对象学习,就是学习创建类(模板),利用类生成实例(月饼)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tWOgO11u-1631802427240)(img/类和实例.jpg)]
对象的读写
var obj = {
name: 'zs',
age: 3,
dd: undefined,
fn: function () {
console.log('前端开发');
}
}
// -----------------------------------
// 读
console.log(obj.name);
console.log(obj['age']);
// -----------------------------------
// 写
obj.name = 'ls';
obj['sex'] = '男';
console.log(obj);
// -----------------------------------
// 遍历
for (var attr in obj) {
console.log(attr, '------', obj[attr]);
}
// -----------------------------------
// in操作符:判断对象是否有这个属性,返回布尔值
// 格式:'key' in 对象
console.log('name' in obj); // true
console.log('sex' in obj); // true
console.log('dd' in obj); // true
console.log('zz' in obj); // false
// -------------------------------
// 删除对象的属性
// 格式:delete 对象.属性
delete obj.name;
console.log(obj);
面向对象创建
字面量创建
// 字面量创建:其实就是 json 形式的对象,适用于创建单个对象。
// 不足:这种创建方式,适用于单个对象的创建,如果要创建多个对象,会代码冗余。
var obj1 = {
name: 'zs',
age: 3,
fn: function () {
console.log('前端开发');
}
}
var obj2 = {
name: 'ls',
age: 2,
fn: function () {
console.log('前端开发');
}
}
实例创建
// 实例创建
// 不足:想创建一个类似的对象,就会产生大量的代码
var obj1 = new Object();
obj1.name = 'zs';
obj1.age = 3;
obj1.fn = function () {
console.log('前端开发');
}
console.log(obj1);
var obj2 = new Object();
obj2.name = 'ls';
obj2.age = 4;
obj2.fn = function () {
console.log('前端开发');
}
console.log(obj2);
工厂模式
// 工厂模式,归根到底就是封装函数
function person(name, age) {
// 1、准备原料
var obj = new Object();
// 2、生产
obj.name = name;
obj.age = age;
obj.fn = function () {
console.log('前端开发');
}
// 3、出厂
return obj;
}
var p1 = person('zs', 3);
console.log(p1);
var p2 = person('ls', 4);
console.log(p2);
instanceof
// 工厂模式解决了重复实例化的问题,但还有一个问题,那就是识别问题,因为根本无法搞清楚他们到底是哪个对象的实例
// instanceof 运算符,一个对象是否为指定的构造函数的实例,返回布尔值
// 语法:实例 instanceof 构造函数;
console.log([] instanceof Array); // true
console.log([] instanceof Object); // true
console.log(p1 instanceof person); // false
console.log(p1 instanceof Object); // true
构造函数模式
构造函数的特点:
构造函数的特点:
1、构造函数名首字母大写(为了区分普通函数,不是必须,是约定)
2、构造函数方法没有显示的创建对象(new Object())
3、直接将属性和方法赋值给 this 对象
4、没有 return 语句,不需要返回对象
5、通过构造函数创建对象,必须使用 new 运算符(直接调用跟普通函数一样)
function Person(name, age) {
this.name = name;
this.age = age;
this.fn = function () {
console.log('前端开发');
}
}
functioin Person (name,age) {
this.name = name;
}
new Person;
构造函数通过new调用
构造函数通过new调用,会经历四步
(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
(3) 执行构造函数中的代码(为这个新对象添加属性);
(4) 返回新对象(隐式的)。
var p1 = new Person('zs', 3);
console.log(p1);
// console.log(p1.name);
// p1.fn();
var p2 = new Person('ls', 4);
console.log(p2);
// var p3 = Person('ww', 5); // 如果不通过new调用,属性加给了window,且没有返回值
// ---------------------------------------
// 构造函数创建解决了 instanceof 识别问题
console.log(p1 instanceof Person); // true
console.log(p1 instanceof Object); // true
// ------------------------------------
// 构造函数创建对象问题:一样的函数会存在多次创建的问题,占用内存空间
// 解决:原型创建对象
alert(p1.fn)
alert(p2.fn)
console.log(p1.fn == p2.fn); // false
对象的比较
// 基本类型:基本类型的比较是值的比较
var a = 3;
var b = 3;
console.log(a == b); // true
// 引用类型:引用类型的比较,是地址的比较
console.log([] == []); // false
console.log(function () { } == function () { }); // false
原型创建对象 (原型与原型链)
1、原型:js每声明一个function,都有prototype原型,prototype原型是函数的一个默认属性,在函数的创建过程中由js编译器自动添加。
也就是说:当生产一个function对象的时候,就有一个原型prototype。原型中存储对象共享的属性和方法。
2、原型链:当查找对象的属性的时候,先找自身,如果自身没有,则找顺着__proto__
找到原型,如果原型也没有,则继续向上找,一直找到Object的原型。这个查找这个链表就是原型链。
// 每声明一个函数,这个函数下面就有一个prototype的属性,它是这个构造函数创建这类实例的原型对象
// 原型对象:是存储这类实例共有属性和方法的地方。原型对象默认会有一个constructor属性,它又指向构造函数
var arr = new Array(); // 创建一个实例(arr就是实例,Array就是构造函数)
console.log(arr);
console.log(arr.__proto__); // 原型对象(通过实例访问)
console.log(Array.prototype); // 原型对象(通过构造函数访问)
console.log(arr.__proto__ == Array.prototype); // true
console.log(Array.prototype.constructor); // 原型对象下面有一个constructor属性,它又指向构造函数
// ---------------------------------------
// 每声明一个函数,它就默认会有一个prototype属性,这个属性里面有一个constructor属性,它又指向这个函数
function fn() { }
console.log(fn.prototype); // {constructor: ƒ}
原型链:
浏览器不显示 proto
浏览器显示 [[Prototype]]
proto= [[Prototype]]
图1
图2
图3
原型创建对象
function Person() { }
// console.log(Person.prototype); // {constructor: ƒ}
// console.log(Person.prototype.constructor); // Person
Person.prototype.name = 'zs';
Person.prototype.age = 3;
Person.prototype.fn = function () {
console.log('前端开发');
}
// console.log(Person.prototype);
// -----------------------------------------
var p1 = new Person();
console.log(p1);
console.log(p1.name); // 'zs'
p1.fn();
console.log(p1.toString);
// 不足:不能传参,创建的人都是一样的
var p2 = new Person();
console.log(p2.name);
// -----------------------
// 原型创建解决了重复创建函数的问题
console.log(p1.fn == p2.fn); // true
6、混合模式创建对象
// 混合模式创建对象 (标准方法)
// 构造函数+原型方式
// 属性写在构造函数里面,方法写在原型上面
function Person(name, age) {
this.name = name;
this.age = age;
}
//Person.prototype.showName = function () {
// console.log(this.name);
//}
//Person.prototype.showAge = function () {
// console.log(this.age);
//}
Person.prototype = {
// 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数
constructor: Star, //地址变了,需要重新指回原地址
showName: function() {
console.log(this.name);
},
showAge: function() {
console.log(this.age);
}
}
var p1 = new Person('zs', 3);
console.log(p1);
p1.showName();
var p2 = new Person('ls', 5);
console.log(p2);
console.log(p2.name);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-30Ey2EMz-1631802427250)(C:\Users\Administrator\Desktop\课堂笔记\第二阶段\笔记\image\混合模式创建对象.jpg)]
7、动态混合模式
// 动态混合模式:给人封装的感觉
function Person(name, age) {
this.name = name;
this.age = age;
if (!Person.prototype.showName) {
Person.prototype.showName = function () {
console.log(this.name);
}
Person.prototype.showAge = function () {
console.log(this.age);
}
}
}
var p1 = new Person('zs', 3);
console.log(p1);
var p2 = new Person('ls', 5);
console.log(p2);
面向对象实例
面向对象的选项卡
原则:先写出普通的写法,然后改成面向对象写法
1、普通方法变型
尽量不要出现函数嵌套函数
可以有全局变量
把onload中不是赋值的语句放到单独函数中(init)
2、改成面向对象()
先写构造函数
onload中创建对象,并init调用
全局变量就是属性
函数就是方法
(属性和方法前面,都要加this)
改this指向问题(尽量让this指向对象)
结论:我们改成面向对象了之后,感觉是不是更复杂了?确实是这样,确实是更复杂了,但是我们这个面向对象特别适合复杂的开发,对于简单的,不太推荐使用面向对象。面对复杂开发时,它特别容易扩展,同时,复用性特别强。上面的例子,多添加几个,就可以发现特别方便复用和扩展。
n(‘zs’, 3);
console.log(p1);
var p2 = new Person(‘ls’, 5);
console.log(p2);
## 面向对象实例
**面向对象的选项卡**
原则:先写出普通的写法,然后改成面向对象写法
1、普通方法变型
尽量不要出现函数嵌套函数
可以有全局变量
把onload中不是赋值的语句放到单独函数中(init)
2、改成面向对象()
先写构造函数
onload中创建对象,并init调用
全局变量就是属性
函数就是方法
(属性和方法前面,都要加this)
改this指向问题(尽量让this指向对象)
**结论**:我们改成面向对象了之后,感觉是不是更复杂了?确实是这样,确实是更复杂了,但是我们这个面向对象特别适合复杂的开发,对于简单的,不太推荐使用面向对象。面对复杂开发时,它特别容易扩展,同时,复用性特别强。上面的例子,多添加几个,就可以发现特别方便复用和扩展。