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;
}
构造函数创建
构造函数特点
-
函数名要大写
-
所有的方法和属性直接加给this
-
必须使用new调用构造函数, 不加new和普通函数没有区别
new的时候发生了什么
-
创建一个空对象
-
将对象的__proto__指向构造函数的prototype
-
this指向空对象,添加属性和方法
-
隐式返回
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);

浙公网安备 33010602011771号