面向对象篇[一]

128 阅读5分钟

一、面向对象

1、创建对象

1.1、字面量

 var obj = {
            name: '风车车',
            age: 20,
            fn() {
                console.log('我是风车车');
            }
        }

1.2、内置构造函数

var obj2 = new Object();
        obj2.name = '假老练'
        obj2.age = 20
        obj2.fn = function () {
            console.log('我是假老练');
}

console.log(obj);
obj.fn();
console.log( obj2);
obj2.fn()

1.3、工厂函数 -- 批量创建对象

function getObj(name,age,sex,email){
            var obj={
                name,
                age,
                sex,
                email,
            }
            return obj
            // var obj =new Object();
            // obj.name=name;
            // obj.age=age;
            // obj.sex=sex;
            // obj.email=email
            // return obj
        }
        let p1=getObj('momo',20,'男','321')
        let p2=getObj('kinkin',20,'女','123')
        console.log(p1);
        console.log(p2);

1.4、字面量/内置构造函数与工厂函数创建对象的弊端

字面量与内置构造函数创建对象的---弊端

​ 无法批量创建对象

工厂函数的----弊端

​ 无法判断对象的类型

1.5、自定义构造函数

// 1.构造函数首字母大写(行业规定)
function Person(name, age, gender) {
//2. 不需要手动创建对象 会自动创
//3. 给this身上添加属性方法
       this.name = name;
            this.age = age;     
            this.gender = gender;
//4. 不需要手动返回对象,对自动返回
}

 // 5.要搭配new 关键字使用(才能创建对象,否则没有意义,并且不安全)
// 语法:var 变量 = new  函数名(实参)
var p=new Person('风车车的主人',20,'男  ')
console.log(p);
console.log(typeof p);

1.6自定义构造函数存在的问题

// 解析 自定义构造函数存在的问题
 function Person(name, age) {
    this.name = name;
     this.age = age;
     this.eat = function () {
//         // 函数存储在  堆内存
         console.log(this.name + '爱吃面');
	}
 }
 var p1 = new Person('lh', 20)
 var p2 = new Person('hl', 18)
 console.log(p1, p2);
// 引用数据类型比较 比较的是引用地址
 console.log(p1.eat === p2.eat); //false 不同引用地址

// 问题 :eat方法做的是同一件事 ,但是占用了两个引用地址
// 解决:使用一个引用地址(全局)存eat函数 ---方法共享
function Person(name, age) {
       this.name = name;
       this.age = age;
       this.eat = eat;
}
//使用函数封装
function eat() {
      console.log(this.name + '爱吃面');
}
var p1 = new Person('lh', 20)
var p2 = new Person('hl', 18)

console.log(p1, p2);
console.log(p1.eat === p2.eat); //true 

问题 :面对对象 --- 对象封装 --- 此时 ,又将方法拿到了全局使用(不符合面向对象的编程思想) 解决:只能在构造函数身上想办法,如果构造函数可以随声存放公共方法 --- 原型对象

2、分析 构造函数搭配new关键字如何创建对象

function Dog(name,age){
// 1.默认创建了一个空对象		  ---- var obj =new Object()
// 2.默认将obj赋值给了this 	----this = obj
// 3.给this添加成员 			 ---  this.xx=xx
	this.name=name;
	this.age=age;
// 4.默认返回了this    ---    return this
}
// 上述步骤,不搭配new 关键字使用 是无效的
var d=new Dog('圆圆',5)
console.log(d);

3.构造函数创建对象分类

目的 :学习 如果进行 对象的 分类 抽象 :将一组对象身上公共特征抽取出来,形成一个类 类 (构造函数,构造器):泛指 一类事物 (人 电脑 狗 门)

对象: 特指 某一个具体事物(这台教师机 ) js中没有严格的类的概念 (js不是面向对象编程语言) js中的类 是 用构造函数模拟的

// 1.对象.constructor 属性 --- 获取构造器(构造函数,类)
console.log(p.constructor === Person);
console.log(d.constructor === Dog);

// 2. instanceof 关键字 属于谁的实例(对象属于这个类码?)
// 对象 instanceof 构造函数 返回一个布尔值
console.log('*****');
console.log( p instanceof Person);
console.log( p instanceof Dog);
console.log( d instanceof Person);
console.log( d instanceof Dog);

二、原型对象

0.1为什么要使用原型对象请看【自定义构造函数存在的问题】

1. 面向对象编程的核心概念

// 构造函数(构造器,类型):和new 一起创建对象  --母亲
// 原型对象:构造函数与生俱来的的对象(夫妻) ---父亲
// 原型成员:原型对象(prototype) 身上的 属性或者方法 eat
 Person.prototype.eat = function () {
      console.log(this.name + '喜欢吃面');
}
// 实例化:构造函数创建实例对象的过程(new)
// 实例对象 :构造函数创建出来的新对象 ----  崽
        var p = new Person('lh', 20);
// 静态成员(showInfo):给构造函数 身上添加的属性或者方法
Persn.showInfo = function () {
       console.log('这是一个人类');
}
// 实例对象可以访问实例成员
console.log(p.name);
console.log(p.age);
// 实例对象可以访问原型成员
p.eat()
// 实例对象不可以访问静态成员
// p.showInfo();
// 只有构造函数可以访问静态成员
Person.showInfo();

2.获取原型对象

2.1、实例对象获取原型对象

// [[prototype]]  就是 __proto__
console.log(p.__proto__);
// 发现:实例对象p身上没有constructor属性,通过 __protot__属性
// 共享原型对象身上的constructor
console.log(p.__proto__.constructor);

2.2、静态方法获取原型对象

// Object.assign() 静态成员
// 需求:使用Object的静态方法 获取 实例对象对应的原型对象
function Person(name, age) {
      this.name = name;
      this.age = age;
}
Person.prototype.eat = function () {
      console.log(this.name + '...');
}

var p = new Person('啊三', 20)
// ****Objet.getPrototypeOf(实例对象)
// Object构造函数身上的静态成员 
//用途:  获取某给实例对象的原型对象
// 注意点:链等(数学写法 ) js不能这么写 
// console.log(Objet.getPrototypeOf(p)===p.__proto__ === Person.prototype);
// 只能
console.log(Objet.getPrototypeOf(p) === p.__proto__ && p.__proto__ === Person.prototype);

3.构造函数创建实例对象的完整过程

function Person(name,age){
	this.name=name;
	this.age=age;
}

Person.prototype.eat=function(){
	console.log(this.name+'..')
}

var p=new Person('||_-.-_||',20)


构造函数创建实例对象的过程(5个步骤)
 function Person(name,age){
// 伪代码
//  1. var obj =new Object()
//  2. obj.__proto__ = Person.prototype
//  3. this =obj
//  4. this.xx=xx
//  5. return this
 }
// 问题: 凭什么p身上__proto__属性指向了Person.prototype
var obj={
    name:'||-..-||'
}
console.log(obj);
// 结论:字面量对象 是Object 构造函数的实例对象
// new 的 过程中 实例对象 的 __proto__ 属性 指向了 构造函数 原型对象
//没有new时 有原型对象吗?
// 使用dir将Person以对象的方式展开
console.dir(Person);
// 结论 : new 与 构造函数有没有原型对象没有关系 ,构造函数的原型对象与生俱来