JS面向对象的编程
函数功能:把所有的功能都的封装在一个函数里,等下次需要实现这个功能时,运行这个方法即可。
面向对象:object oriented programming 以对象数据类型为导向的编程
单例模式:
概念:将同一事物的属性和方法封装在一个空间(对象)里
防止代码冲突和覆盖
不同模块之间获取属性:通过模块名.方法名()
同一模块之间获取属性:this.方法名()
//单例模式是敞开型的 var login = { username: 'lucy', password: '123456', email: function(){ console.log('email')}, fn:function(){console.log(1)}, fn1:function(){ this.fn();//调用同一模块方法 console.log(2)} }; login.fn1(); //调用fn1方法 var register = { username: 'lucy', password: '123456', fn2:function(){ this.username; this.password;}, fn1:function(){ login.email()//不同模块调用 } }
高级单例模式:
单例模式里的任何内容都能被提取;但有些内容是模块私有的,只有这个模块内部才能调用,若要公有,得经过处理,把需要暴露的东西放在return后的对象中返回。
解决私有和共享问题
var login = (function(){ var username = 'Lily'; var password = '123456'; function email(){ console.log('email'); } function check(){ console.log('check'); } return { email: email(), } })()//小括号必须写 是把自执行函数返回的结果给了login 而不是把函数给了login var register = { fn: function(){ login.email; //调用login里的email方法 console.log('email'); } } register.fn();
工厂模式:
单例模式属于手工作坊式(一遍一遍执行),''批量生产''需要使用工厂模式
共三步 生产出来的是一模一样的东西
function shirt(){ //1:创建对象 var obj ={}; //2:给对象添加属性(把需要实现的功能放在对象里) obj.size = 'xl', obj.material = '棉', obj.fn = function{ console.log('fn'); } //3:返回对象 return obj; } for(var i = 0; i < 1000; i++){ console.log(shirt());//运行1000次 }
构造函数模式:
对象:万物皆对象
类:对象中细分的类型
实例:某类中实实在在的事物(具体的事物)
ES5中类叫构造函数 ES6中 class 才叫类
JS中的内置类:
Number String Boolean Null Undefined Object Array RegExp Date Functon 小写叫数据类型
Number String Boolean 包装类
var num = 10;//可以操作的具体的事物 实例 属于Number类 var str = 'abc';//String类的实例 var num = new Number(10); //Number{10} 对象10 num = num.valueOf(); //10 基本数据类型 var ary = new Array(10);//参数是数值 表示数组长度 var ary = new Array('abc');//表示数组中有一项是abc var ary = new Array(10, 20);//超过两项 表示数组有两项10,20
自定义类
为了和普通函数区别:首字母要大写
function Person(){ //为了和普通函数区别:首字母要大写 //1.创建对象(系统自己创建) //2.给对象添加属性(对象用this来表示) this.name = 'Lily'; //this称为实例 this.age = 20; this.writeCss = function () { console.log('writeCss'); } //3.返回对象(系统自己返回) } //Person();//这样运行--->Person就是普通函数,this指的是window var p1 = new Person(); //通过new运算符运行的函数称为构造函数 称为Person构造函数(Person类) p1指的是返回的对象 也就是Person类的实例 var p2 = new Person(); console.log(p1, p2);
函数细节知识:
1.若不需要传参,小括号可以省略
2.this指的是实例,跟this.xxx有关,跟私有变量无关
3.只要在构造函数中定义的属性,都是实例私有的属性(有实例都要用的功能公有的功能不能把他放在构造函数里,放在原型上)
4.return不用写。若必须写,return后面跟基本类型数据,对return没有影响,return后面跟引用类型的数据会把实例覆盖
function Person(name, age){ var name = 'Lily'; //私有变量name this.name = name; this.age = age; this.fn = function(){ console.log('fn'); } } var p1 = new Person('Lucy', 22); console.log(p1.name); //跟私有变量无关 ``` ``` function Person(name, age){ this.name = name; this.age = age; this.fn = function(){ console.log('fn'); } } var p1 = new Person('Lucy', 22); var p2 = new Person('Lily',10); console.log(p1.fn == p2.fn);//false ``` ``` function Person(name, age) { this.name = name; this.age = age; } Person.prototype.fn = function (){ console.log('fn'); };//每个实例都共有的 放在原型上 var p1 = new Person('Lucy', 22); var p2 = new Person('Lily',10); console.log(p1.fn == p2.fn);//true
原型模式
记住三句话:
1.所有的函数都有一个属性叫`prototype`属性,prototype指向默认的原型对象
2.默认的原型对象上有个属性叫`constructor`,它指向构造函数
3.所有的对象上都有一个属性`__proto__`,它指向所属类的原型(IE不支持)
`Object.prototype`没有下划线`__proto__`(原本应该有但是没有,为null)
function Person(name, age) { this.name = name; this.age = age; } Person.prototype.fn = function (){ console.log('fn'); };//每个实例都共有的 放在原型上 var p1 = new Person('Lucy', 22); var p2 = new Person('Lily',10); console.log(p1.fn === p2.fn);//true console.log(Person.prototype.__proto__ === Object.prototype);//true console.log(p1.__proto__ === Person.prototype);//true console.log(p1.__proto__.__proto__ === Object.prototype);//true
- hasOwnProperty
:检测是否是一个私有属性
- isPrototypeOf
检测一个对象是否在另一个对象的原型链上
- propertyIsEnumerable
:属性是否是可枚举的
- toString
转换成字符串
思考题:封装一个方法hasPublicProperty:检测一个属性是否是共有的
- 用
in
来判断属性是否在原型链上 - 查找属性的顺序:
- 1.若实例上有,则不会继续往上查找
- 2.实例上没有,则通过
__proto__
去所属类的原型上找,若还没有找到,则继续通过__proto__
查找,一直找到Object类
的原型,若还是没有找到,则是undefined
注意:通过
__proto__
查找所属类的原型,一级级往父类的原型找,就形成了原型链__proto__
是实现继承
的关键
原型上扩展方法
- 内置类原型上的方法可以一个一个修改,但不能批量修改
__proto__
IE浏览器不支持
原型上 链式调用
return this
实现链式调用的关键
深入函数
- 普通函数
- 构造函数
- 对象
- 增删改查
若函数当成对象时,函数名就相当于对象名
当成函数时,有一个属性
prototype
,指向原型对象
当成对象时,有一个属性__proto__
,指向所属类(Function类)原型
—>由此证明:所有的函数都是Function类
的实例
面试题
阿里面试:
Function类
call``apply``bind
- 作用:用来改变方法里的.之前的this关键字
call
- 第一个参数用来改变点前面方法里的
this
关键字,第二个参数开始会当成实参传给.前面的方法(传参方式:散列式
) - 调用方法:
- 1.Function.prototype.call;
- 2.fn.call;
说明:
Function.prototype.call = function(){
//1.把实例(点前面的方法)中的this改成第一个参数
//2.把实例运行
}
apply
- 参数:两个参数。第一个参数用来改变.前面方法里的
this
,第二个数组
或者类数组
然后一起传给.前面的方法(传参方式:打包式的
) - 传参时是打包式的,但是实参传给形参时,还得把实参里的内容拿出来,一个一个传给形参(第一项给第一个形参,第二项给第二个形参)
bind
柯里化函数(预处理思想)
- 第一个参数:改变.前面的
this
关键字(传参方式:同call
,都是散列式) - 把所有的参数返回给.前面的方法后,返回一个需要执行的小函数,想要执行时要自己手动执行