原生javascript面向对象
亲爱的小伙伴们,有么有男朋友或者是女朋手啊!今天要说面向对象了,都准备好面向对象了吗?
一、什么是面向对象?
(1)面向对象不是一门技术,而是一种处理问题的思路,一种编程思想,是对传统面向过程编程的一种补充和完善。
(2)面向对象,是将程序中的数据和功能进行封装,通过面向对象的三大特征封装、继承、多态以达到代码复用性、低耦合、增强代码功能扩展。
(3) 面向对象已经被广泛应用于各种编程语言中,是当下流行的一种编程语言处理需求的概念。
(4)面向对象的核心就是类和对象的抽象封装和创建,通过创建的各种对象之间互相协作(互相调用函数)来完成一个功能的完整流程。
二、面向对象和类的区别
面向对象的类:类型的简称,就是一个代号,一种数据类型的描述,说白了,类是对象抽象出来的概念。
对象:就是类型的某一个具体的实体,一个具体存在的实际物体,对象是类型指代的具体存在的某一个物体。
三、面向对象的封装
( 1)原始的封装模式:通过JSON数据来模拟一种数据类型
(2)特点:对零散数据进行封装。
(3)缺陷: kangKang[对象]和People[类]之间没有任何关系
kangKang[对象]和houZi[对象]之间没有任何关系
这样的封装模式下,如果对象比较多,就会让代码的复杂度提升的非常严重
kangKang[对象]和houZi[对象]之间没有任何关系
这样的封装模式下,如果对象比较多,就会让代码的复杂度提升的非常严重
以下为例;
/* 1.1 定义一个李达康书记?*/
/* 只是开发人员自己人为规定了,四个变量用来描述一个人物对象 */
var _name = "李达康";
var _age = 48;
var _job = "市委书记";
var _wife = "欧阳菁";
var _name2 = "候亮平";
var _age2 = 45;
var _job2 = "侦查处长";
var _wife2 = "局长";
人:一种类型,一种数据类型,简称类
和整数类型、浮点数类型、字符串类型等等一样,就是一种数据类型
*/
var People = {/*模拟定义了一个人的类型【数据类型】*/
name:"",
age:0,
job:"",
wife:""
};
var kangKang = {};
kangKang.name = "李达康";
kangKang.age = 48;
kangKang.job = "市委书记";
kangKang.wife = "欧阳菁";
var houZi = {};
houZi.name = "侯亮平";
houZi.age = 45;
houZi.job = "反贪局长";
houZi.wife = "某局长";
console.log(kangKang);
console.log(houZi);
</script>
四、面向对象的第二种封装
这种封装模式是为了解决第一种封装中由于代码的重复量造成的复杂度的提升
以下为例:
function People (name, age, job, wife) {
return {
name:name,
age:age,
job:job,
wife:wife
}
}
// 直接用就会特别简单
var kangKang = People("李达康", 48, "市委书记", "欧阳菁");
var houZi = People("侯亮平", 45, "反贪局张", "某局长");
console.log(kangKang, houZi);
</script>
第二种封装出现的问题:
(1)对象和类之间没有任何关系
(2) 同一个类的多个对象之间没有任何关系
第二种封装应该怎么用:
(1)单例模式:当程序中,某个对象只能出现一次的时候。使用JSON对象直接封装
(2)当程序中的某个类型可能出现多个对象的时候,不要使用这样的形式封装。
四、面向对象——构造函数封装对象
构造函数封装对象时的思路:
(1)面向:设身处地(2)面向对象:当你就是将要封装的对象,你自己会有哪些特征,会有哪些行为
(3) 站在对象的角度思考问题~面向对象 Oriented Object 分析过程
(4)如果通过构造函数创建对象,使用new关键字来进行对象的创建
小伙伴们最近有么有看人民的民义呢?那我们就以人民的民义中的任务为例
1.人民的名义
* 侯亮平 陈海 季昌明
*
* 抽象/抽取:姓名、性别、检察官
*
以下为代码:
var People = function(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.search = function() {
console.log("搜查令......");
}
}
var houZi = new People("侯亮平", 45, "男");
var chenHai = new People("陈海", 42, "男");
实例对象,有一个constructor属性,指向的是创建自己的构造函数
两个对象之间的关系,都是通过同一个构造函数创建出来的
如:
console.log(houZi.constructor);
console.log(chenHai.constructor);
console.log(houZi.constructor == chenHai.constructor);
对象和类型之间的关系,对象是否某种烈性:通过instanceof 关键字来判断
如:
console.log(houZi instanceof People);//houZi是否是People类型
console.log(chenHai instanceof People);//houZi是否是People类型
五、内存分析
1、变量中存储的都是基本类型的数据
以下为代码
var x = 1;
var y = 12;
var z = x + y ;
console.log(z);
当变量中存放的是对象时
var People = function(name) {
this.name = name;
}
// People: 自定义数据类型——引用类型
// p1:引用变量
var p1 = new People("tom");
var p2 = new People("jerry");
console.log(p1 == p2);
var p3 = p1;// 做了什么事情?
console.log(p1 == p3);
p3.name = "shuku";
console.log(p1.name);
关于函数传递基本类型参数的问题
function fn1(num) {
num = 12;
}
var x = 10;
fn1(x);
console.log(x);// 值为10
/*function fn2(num) {
num = 12;
return num;
}
var x = 10;
x = fn2(x);
console.log(x );// 值为12*/
传递引用类型的操作
function fnx1(obj) {
obj.name = "damu";
}
var px = new People("tom");
fnx1(px);
console.log(px.name);// damu
function fnx1(obj) {// abcde1
obj = new People("damu");// qwerad
obj.name = "jerry";
}
var px = new People("tom");// abcde1
fnx1(px);// abcde1
console.log(px.name);// tom
六、字符串内存分析
<script>
var s1 = "hello";// 字面常量
var s2 = "hello";
var s3 = new String("hello");
var s4 = new String("hello");
console.log(s1 == s2);// true
console.log(s1 === s2);// true
console.log(s1 == s3);// true
console.log(s1 === s3);// false
console.log(s3 == s4);// false
console.log(s3 === s4);// false
console.log(typeof s1, typeof s3);
</script>
六、继承
var People = function(name) {
this.name = name;
this.eat = function() { // 吃饭,每个对象不一样
console.log(this.name + "吃饭了.....");
}
/*this.run = function() { // 跑步,每个对象都一样
console.log("跑步锻炼");
}*/
}
People.prototype.job = "检察官"; //定义公共属性
People.prototype.run = function() { // 定义公共函数
console.log("跑步锻炼........");
}
var tom = new People("tom");
var jerry = new People("jerry");
/*console.log(tom.job);
tom.eat(); //直接调用eat()
tom.run(); //直接调用run()
console.log(jerry.job);
jerry.eat();
jerry.run();*/
console.log(tom, jerry);
</script>
继承是用来做什么的: 继承是通过子类继承父类实现父类中代码的重复利用!
继承的第一种方式:通过apply/call实现假继承
apply/call方法都是通过改变函数中第一个参数的指向来达到扩展代码功能的目的
apply/call方法都是通过改变函数中第一个参数的指向来达到扩展代码功能的目的
*var Animal = function(name, color) {
this.name = name;
this.color = color;
}
Animal.prototype.eat = function() {console.log("吃肉");}
var Cat = function(name, color, age, type) {
// Animal.apply(this, [name, color]);
Animal.call(this, name, color);
this.age = age;
this.type = type;
}
Cat.prototype.caches = function() {console.log("抓老鼠..");}
var cat = new Cat("tom", "黑色", 48, "猫科");
console.log(cat);*/
通过prototype和空对象进行间接继承
var _extends = function(Child, Parent) {
var F = function() {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
var Animal = function(name,age) {
this.name = name;
this.age = age;
}
Animal.prototype.play = function() {console.log("play gaming!");}
var Cat = function(name, age, color) {
this.color = color;
}
_extends(Cat, Animal);
var cat = new Cat();
console.log(cat);
七、封装原则
常规情况下,对于对象的封装,一是将属性封装在构造函数的内部。二是将行为定义到构造函数的prototype上面
var Person = function(name, age) {// 构造函数中只封装属性
this.name = name;
this.age = age;
}
Person.prototype.run = function() {};
Person.prototype.sleep = function() {};
Person.prototype.play = function() {};
/* prototype 的使用 */
Array.prototype.getMax = function() {
var _max = this[0];
for(var i = 0; i < this.length; i++) {
if(this[i] > _max) {
_max = this[i];
}
}
return _max;
}
var _arr = [1,3,4,2,21,4,65,6,2,4];
/*console.log(Math.max(1,3,4,2,21,4,65,6,2,4));
console.log(Math.max.apply(null, _arr));*/
console.log(_arr.getMax());
</script>