目录
面向对象(OOP)和this的处理
* 面向对象
JS是一门编程语言(具有编程思想)
【面向对象】JS\JAVA\PHP\Ruby\Python
【面向过程】C\C++
【面向对象编程】 对象、类、实例
- 对象:万物皆对象
- 类:对象的具体细分(按照功能特点进行分类:大类、小类)
- 实例: 类中具体的一个事物(拿出类中的具体一个实例进行研究,那么当前类下的其他实例也具备这些特点和特征)
整个JS就是基于面向对象设计和开发出来的语言,我们学习和实战的时候也要按照面向对象的思想去体会和理解
【JS中的内置类】
一 单例设计模式(Singleton Pattern)
- 单例设计模式解决的问题
- 表现形式:
var obj={
name:"dxy",
age:18
};
//在单例设计模式中,obj不仅仅是对象名,**它被称为命名空间**把描述事物的属性存放到命名空间中,多个命名空间是独立分 //开的,互不冲突。
- 作用:把描述同一件事物的属性和特征进项 分组 、分类(存储在同一个堆内存空间中),因此避免了全局变量之间的冲突和污染。
var obj1={name:"xxx"}
var obj2={name:"xxx"}
obj1!=obj2
- 为什么叫做单例设计模式:
每一个命名空间都是JS中Object这个内置基类的实例,而实例之间是相互独立互不干扰的,所以我们称之为单例
,单独的实例。
- 高级单例模式
- 在给命名空间赋值的时候,不是直接赋值一个对象,而先执行一个匿名函数,形成一个私有作用域AA(不销毁的栈内存),在AA中创建一个堆内存,把堆内存地址赋值给命名空间。
- 这种模式的好处:
我们完全可以在AA中创造很多内容(变量或者函数),那些需要供外面调用,我们就暴露到返回对象中(模块化实现的一种思想)。
var nameSpace=(function(){
var n=12;
function fn(){
//...
}
return {
fn:fn //创建堆内存
}
})();
- 基于单例模式实现模块化开发
- 模块化开发
1.1 团队协作开发的时候会把产品按照功能模块进行划分,每一个模块有专门人负责开发
1.2 把各个板块之间公用的部分进行提取封装,后期想实现这些功能,直接调取应用即可(模块封装)
- 模块化开发
//模块封装
var skipRender=(function(){
var fn=function(){};
return {
init:function(){
},
fn:fn
}
})();
skipRender.init();
//天气模块
var weather=(function(){
var fn=function(){
};
return {
init:function(){
fn();//调取自己模块中的方法直接调用即可。
skipRender.fn();
}
}
})();
weather.init();
【工厂模式(Factory Pattern)】
- 把实现相同功能的代码进行封装,以实现
批量生产
,后期我们想要实现这个功能,我们只需要执行函数即可。 低耦合高内聚
:减少页面中的冗余代码,提高代码的重复使用率。
function createPerson(name,age){
var obj={};
obj.name=name;
obj.age=age;
return obj;
}
var p1=createPerson("hhh",10);
var p1=createPerson("xxx",18);
二 类和实例
三 constructor 构造函数设计模式
- 基于构造函数创建基本值
- 在普通函数执行的基础上
new XXX()
,这样就不是普通函数执行了,而是构造函数执行,当前函数名称之为“类名”,接收的返回结过为当前类的一个实例。 - 自己创建类名最好第一个单词首字母大写。
- 这种构造函数设计模式执行主要用于组件、类库、框架等的封装,平时编写业务逻辑一般不这样处理。
function Fn(){
}
Fn();// 普通函数执行
var f=new n();//Fn为类new-->构造函数 f为类的一个实例有值
var f2=new n();//创建第二个实例,两个实例间互不影响
- JS中创建值有两种方式,
- 字面量表达式
- 构造函数模式
var obj={};//zi字面量表达式
var obj=new Object();//构造函数模式 创建出来是个空对象
不管是哪种方式创造出来都是Object的实例,而实例间是独立分开的,所以var xxx={ }这种模式就是JS的单例模式
。- 基本数据类型基于两种不同的模式创建出来的值是不一样的
var num1=12; //number
var num2=new Number(12);//object
区别
4.1 基于字面量方式创建出来的是基本类型值,
4.2 基于构造函数创建出来的是引用类型
相同点
4.3 num2是数字类的实例;num1也是数字类的实例,它只是JS表达数字的特殊方式之一;都可以使用数字类提供的属性和方法。
- 自定义类的创建
- instanceof
检测某一个实例是否隶属这个类
缺 点:
1 instanceof Number//false
function Fn(){
var n=0;
this.m=n;
}
var f=new Fn();
console.log(f instanceof Fn);//true
console.log(f instanceof Array);//false
console.log(f instanceof Object);//true 万物皆对象
console.log('m' in f);//true
console.log('n' in f);//false n仅仅为私有变量和属性没有关系
console.log('toString' in f);//true 共有属性
console.log(f.hasOwnproperty('toString'));//false
in
检测某个对象是否有某个属性
不管当前这个属性是对象的私有属性还是共有属性,只要有结果就是truehasOwnProperty
:检测当前属性是否为对象的私有属性
不仅要有这个属性还必须为私有属性
四 new运算符的实现机制
- 普通函数执行
- 形成一个私有作用域
- 形参赋值
- 变量提升
- 代码执行
- 栈内存释放问题
- 构造函数执行
function Fn(){
}
Fn();
function Fn(name ,age){
var n=10;
this.name=name;
this.age=age+n;
}
var f1=Fn('dxy',12);
- 图解普通函数执行和构造函数执行
注意:f1.n 为undefined ,只有this.xxx=xxx才和实例有关系,n是私有作用域中的一个私有变量而已(this是当前类的实例)
- 若构造函数中有return
不写return浏览器会默认返回创建的实例;
写了return
- 如果return 是一个基本值 ,返回依然是类的实例;
- 如果返回的是引用值,则会把默认返回的值覆盖,此时接收到的结果不是当前实例。
注意:构造函数执行的时候,尽量减少return的使用,防止覆盖实例
return;
是代码结束的作用,不会覆盖返回的实例。
function Fn(){
var n=0;
this.m=n;
//return 'hh';
return {name:'hh'};
}
var f=new Fn();
console.log(f);//{name:"hh"} 被覆盖
new Fn
和new Fn()
在构造函数执行的时候,如果Fn 不需要传参,我们可以省略小括号,也是创建实例,两者没有区别。
五 原型和原型链
原型链设计模式
原型(prototype)、原型链(proto)
[函数]
普通函数,类(所有的类:内置类,自己创建的类)new xxx(),Date
[对象]
普通对象,数组,正则,Math ,实例是对象类型(除了基本类型的字面量创建的值),arguments…
prototype的值也是对象类型,
函数也是对象类型
。。。。
- 所有的函数类型天生都自带一个属性:prototype(原型),这个属性的值是一个对象 ,浏览器默认会给它开辟一个堆内存;
- 在浏览器给prototype开辟的堆内存中有一个天生自带的属性:constructor,这个属性存储的值是当前的函数本身。
- 每一个对象都有一个__proto__的属性,这个属性指向当前实例所属类的prototype。如果不确定它是谁的实例,那么都为Object的实例。
- 原型链机制
通过__proto__隐式原型链向上查找的机制;
当我们操作实例的某个属性或者方法的时候,首先找自己空间中私有的属性和方法;
+ 若找到,结束查找,使用自己私有的即可
+ 若没找到,则基于__proto__找所属类的prototype,如果找到就用共有的,如果没找到,基于原型上的__proto__进行查找,一直找到Object.prototype的原型为止,如果还是没有,操作的属性或者方法不存在。
图解如下:
原型链试炼:
function Fn(){
var n=100;
this.AA=function(){
console.log("A【私有属性】");
};
this.BB=function(){
console.log("B【私有属性】");
};
}
Fn.prototype.AA=function(){
console.log("A【公有属性】");
}
var f1=new Fn; //无参可以省略小括号
var f2=new Fn;
f1.n; // undedined
console.log(f1.n);
f1.AA===f2.AA; //false
f1.__proto__.AA===f2.__proto__.AA;//true
f1.__proto__.AA=Fn.prototype.AA; //true
f1.hasOwnProperty===Fn.prototype.hasOwnProperty;//true
f1.name=XX;//给自己设置私有属性
f1.__proto__.name=XXX;//给原型设置共有属性
Fn.prototype=XXX; // 给原型设置共有属性
题目图解分析:
- hasOwnProperty
- 原型链中的this问题
- 基于内置类原型扩展方法
六 JS 中五种 this 情况综合梳理
- 给当前元素的某个
事件绑定
方法,当某个事件触发执行的时候,方法中的this是当前操作的元素对象
oBox.onClick=function(){
//=>this: oBox
}
普通函数执行
,函数中的this取决于执行主体,谁调用this就是谁(执行主体,方法名前是否有”点“,有的话,点前边是谁,this就是谁,没有的话,this就是window)
function fn(){ //=>AAAFFF000
console.log(1);
};
var obj={fn:fn};
obj.fn(); // this:obj
fn(); // this:window
~function(){
}(); //this:window 自执行函数执行方法中的this是window
习题练习
var n=2;
var obj={
n:3,
fn:(function(n){
n*=2;
var n=5;
this.n+=2;
return function(m){ //产生闭包
this.n*=2;
console.log(m+(++n));
}
})(n) //obj.n会报错
};
var fn=obj.fn;
fn(3); //9
obj.fn(3);//10
console.log(n,obj.n);//8 6
- 构造函数指行
- 箭头函数this指向
- call/apply/bind
七 call/apply/bind
八 JS中四大继承方案
九 深拷贝and浅拷贝
请参考
https://blog.csdn.net/baidu_36065997/article/details/80309991
学习中的知识总结,会持续更新哦,有什么问题,欢迎大家指正