一、面向对象
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 与 构造函数有没有原型对象没有关系 ,构造函数的原型对象与生俱来