30 面向对象、面向对象创建、面向对象的继承

30 面向对象、面向对象创建、面向对象的继承

面向对象

概念

面向过程: 注重过程

面向对象: 注重结果

核心:使用对象

有对象 就用对象 没有对象 创建对象

对象由属性和方法组成

属性: 描述 静态的

方法: 行为 动态的

var 变量 = {

属性名: 属性值,

方法名: 函数

}

类: 模板

实例化对象: 将一个模型变成具体的对象的过程

es5没有类的概念 通过模板创建出很多类似的对象 函数

特性: 封装 继承

面向对象创建

字面量创建

var 变量 = {

属性名: 属性值,

方法名: 函数

}

优点: 直观

缺点: 只适合单个对象的创建

var obj = {
   name: '彭于晏',
   tip: function(){
       console.log('长得帅');
  }
}
console.log(obj);

new创建

var 变量 = new Object();

变量.属性名 = 属性值;

缺点: 代码冗余

var obj = new Object();
obj.name = '蔡徐坤';
obj.tip = function(){
   console.log('唱跳rap篮球');
}
console.log(obj);
obj.tip();

工厂创建

问题: 识别不清

var obj = createObj('蔡徐坤', 22);
var obj1 = createObj('李易峰', 32);
console.log(obj, obj1);
console.log(typeof obj); // 检验出来数据类型

// 对象 instanceof 函数名
console.log(obj instanceof createObj); // false 不是这个工厂创建出来的

function createObj(name, age) {
   // 1. 创建一个空对象
   var obj = new Object();

   // 2. 添加属性和方法
   obj.name = name;
   obj.age = age;
   obj.tip = function () {
       console.log('唱跳rap篮球');
  }

   // 3. 设置返回值
   return obj;
}

构造函数创建

构造函数特点
  1. 函数名要大写

  2. 所有的方法和属性直接加给this

  3. 必须使用new调用构造函数, 不加new和普通函数没有区别

new的时候发生了什么
  1. 创建一个空对象

  2. 将对象的__proto__指向构造函数的prototype

  3. this指向空对象,添加属性和方法

  4. 隐式返回

function CreateObj(name, age) {
   // 1. 创建一个空对象
   // var obj = new Object();

   console.log(this);

   // 2. 添加属性和方法
   this.name = name;
   this.age = age;
   this.tip = function () {
       console.log('唱跳rap篮球');
  }

   // 3. 设置返回值
   // return obj;
}

var obj = new CreateObj('胡歌', 33);
var obj1 = new CreateObj('蔡徐坤', 33);
console.log(obj, obj1);

obj.tip();
obj1.tip();

console.log(obj.tip, obj1.tip);
console.log(obj.tip == obj1.tip); // false

// 缺点:内存浪费

原型

原型对象: 函数 prototype

原型属性: 实例化对象 proto

constructor: 指向创建对象的函数

原型对象和原型属性是同一个

原型: 用来存储当前最顶层的共享的方法和属性

function CreateObj(name, age){
   // 添加给this
   this.age = age;
   this.name = name;
   this.tip = function(){
       console.log('长得帅');
  }
}

var obj = new CreateObj('蔡徐坤', 33);
console.log(obj);
console.log(CreateObj.prototype);
console.log(obj.__proto__);
// 复杂数据类型判断是否是同一个内存位置上的数据 == true--是同一个 false--不是
console.log(obj.__proto__ == CreateObj.prototype); // true

console.log(obj.__proto__.constructor); // 创建对象的函数

console.log(obj.__proto__.constructor == CreateObj); // true

原型创建

问题: 1. 不能传参

\2. 一改全改

function CreateObj(){}
// 属性和方法添加给原型对象
CreateObj.prototype.name = '张三';
CreateObj.prototype.age = 33;
CreateObj.prototype.cc = ['余额宝', '理财', '银行'];
CreateObj.prototype.tip = function(){
   console.log('挣得多');
}

// 实例化对象
var obj = new CreateObj();
var obj1 = new CreateObj();
console.log(obj, obj1);
console.log(obj.name, obj1.name);
obj.tip();
obj1.tip();

console.log(obj1.tip == obj.tip); // true

console.log(obj.cc, obj1.cc);
// obj 多加了一个 基金
obj.cc.push('基金');

console.log(obj.cc);
console.log(obj1.cc);

混合创建

构造函数(动态性 可变的) + 原型创建(静态 不变的)

function CreateObj(name, age) {
   this.name = name;
   this.age = age;
   this.cc = ['余额宝', '理财', '银行'];
}

CreateObj.prototype.tip = function () {
   console.log('挣得多');
}

// 实例化对象
var obj = new CreateObj('蔡徐坤', 33);
var obj1 = new CreateObj('胡歌', 33);
console.log(obj, obj1);

obj.cc.push('基金');
console.log(obj.cc, obj1.cc);

console.log(obj.tip == obj1.tip);

动态混合创建

判断 判断添加的方法是否是期望结果 tip是不是函数 如果不是函数 设置成函数

由于混合创建破坏了面向对象的封装的特性

function CreateObj(name, age) {
   this.name = name;
   this.age = age;
   this.cc = ['余额宝', '理财', '银行'];

   // 判断 判断添加的方法是否是期望结果 tip是不是函数 如果不是函数 设置成函数
   if(typeof(CreateObj.prototype.tip) != 'function'){
       console.log(1);
       CreateObj.prototype.tip = function () {
           console.log('挣得多');
      }
  }
}


// 实例化对象
var obj = new CreateObj('蔡徐坤', 33);
var obj1 = new CreateObj('胡歌', 33);
console.log(obj, obj1);

obj.cc.push('基金');
console.log(obj.cc, obj1.cc);

console.log(obj.tip == obj1.tip);

命名空间

当项目足够大的时候 变量名不够用的情况

将所有的变量都作为对象的一个属性来存储

var taobao = {
nav: {},
banner: {}
};
taobao.nav.title = '标题啊';
taobao.banner.title = 'banner';
console.log(taobao);

改变this指向

call

apply

作用: 改变this指向

call: 函数/方法.call(this的新指向, 实参1, 实参2,....);

apply: 函数/方法.apply(this的新指向, [实参1, 实参2,....]);

var obj = {
name: '张三',
callme: function(a, b){
console.log(this.name);
console.log(a, b);
}
}
// obj.callme(); // 张三
obj.callme(10, 20); // 张三

var obj2 = {
name: '彭于晏'
}
// obj.callme.call(obj2);
// obj.callme.apply(obj2);

obj.callme.call(obj2, 40, 50);
obj.callme.apply(obj2, [40, 50]);

面向对象的继承

原型链继承

子类构造函数的原型对象 = 父类构造函数的实例化对象

问题: 引用数据类型 一改全改

// 1. 父类构造函数
function Father(name, age){
this.name = name;
this.age = age;
}
Father.prototype.tip = function(){
console.log('推脱');
}
// 2. 子类构造函数
function Son(name, age){
// this.name = name;
this.age = age;
}

// 3. 子类构造函数的原型对象 = 父类构造函数的实例化对象
Son.prototype = new Father('郑爽', 33);

// 实例化子类构造函数对象
var obj = new Son('女儿', 1);
console.log(obj);

console.log(obj.name);
console.log(obj.tip);
console.log(obj.toString);
console.log(obj.toA);

原型链

当一个对象或函数被创建的时候所形成的链表关系

实现继承和查找

找的过程: 先找自身,如果自身有就返回,如果自身没有,找自身的原型属性也就是父类构造函数的实例化对象, 如果没有, 找父类构造函数的原型对象, 如果没有, 找object, 找到null都没有, 返回undefined

 

对象冒充继承

在子类构造函数中, 调用父类构造函数, 改变this指向

问题: 不能继承父类构造函数上的原型对象的属性和方法

// 1. 父类构造函数
function Father(name, age){
this.name = name;
this.age = age;
this.arr = [2,3,4];
}
Father.prototype.tip = function(){
console.log('推脱');
}
// 2. 子类构造函数
function Son(name, age){
// 3. 调用父类构造函数 改变this指向
// this--->子类构造函数创建的对象
// 把自己变成父类构造函数的对象
console.log(this); // 表示自己创建出来的对象
Father.call(this, name, age);
}

// 实例化对象
var obj = new Son('儿子', 3);
var obj1 = new Son('儿子1', 13);
console.log(obj, obj1);
console.log(obj.arr, obj1.arr);
obj.arr.push(6);
console.log(obj.arr, obj1.arr);
console.log(obj.tip);

 

组合继承

原型链 + 对象冒充

// 1. 父类构造函数
function Father(name, age){
this.name = name;
this.age = age;
this.arr = [2,3,4];
}
Father.prototype.tip = function(){
console.log('推脱');
}
// 2. 子类构造函数
function Son(name, age){
// 3. 调用父类构造函数 改变this指向
console.log(this); // 表示自己创建出来的对象
Father.call(this, name, age);
}
// 4. 原型链继承 子类构造函数的原型对象 = 父类构造函数的实例化对象
Son.prototype = new Father();
// 实例化对象
var obj = new Son('儿子', 3);
var obj1 = new Son('儿子1', 13);
console.log(obj, obj1);
obj.arr.push(6);
console.log(obj.arr, obj1.arr);
console.log(obj.tip);

 

寄生式组合继承

// 1. 父类构造函数
function Father(name, age) {
this.name = name;
this.age = age;
this.arr = [2, 3, 4];
}
Father.prototype.tip = function () {
console.log('推脱');
}
// 2. 子类构造函数
function Son(name, age) {
// 3. 调用父类构造函数 改变this指向
console.log(this); // 表示自己创建出来的对象
Father.call(this, name, age);
}


function inherit(father, child) {
// 创一个空函数---> 模拟父类构造函数
var F = function () { };
F.prototype = father.prototype;
// 4. 原型链继承: 子类构造函数的原型对象 = 父类构造函数的实例化对象
child.prototype = new F();
child.prototype.constructor = child;
}
inherit(Father, Son);

var obj = new Son('123', 12);
console.log(obj);

 

posted @ 2021-05-07 21:59  一花一世界111  阅读(44)  评论(0)    收藏  举报