函数功能:把所有的功能都的封装在一个函数里,等下次需要实现这个功能时,运行这个方法即可。
面向对象: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不支持) ![Alt text](./1536641006111.png) `Object.prototype`没有下划线`__proto__`(原本应该有但是没有,为null) ![Alt text](./1536641183313.png) ``` 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 ``` ![Alt text](./1536650289036.png) - `hasOwnProperty`:检测是否是一个私有属性 - `isPrototypeOf`检测一个对象是否在另一个对象的原型链上 - `propertyIsEnumerable`:属性是否是可枚举的 - `toString` 转换成字符串 思考题:封装一个方法hasPublicProperty:检测一个属性是否是共有的 ``` function hasPublicProperty(obj, attr) { if(attr in obj) { if (obj.hasOwnProperty(attr)) console.log('私有属性'); else console.log('共有属性'); }else{ console.log('不是它的属性'); } } function Fn(){ this.name = 'Lily'; } Fn.prototype.fn = function () { console.log('a') }; Fn.prototype.age = 26; var f1 = new Fn(); hasPublicProperty(f1, 'name');//私有属性 hasPublicProperty(f1, 'fn'); //共有属性 hasPublicProperty(f1, 'age'); //共有属性 console.log('hasOwnProperty' in f1); //true //属性是否在f1对象的原型链上 ``` - 用`in`来判断属性是否在原型链上 - 查找属性的顺序: - 1.若实例上有,则不会继续往上查找 - 2.实例上没有,则通过`__proto__`去所属类的原型上找,若还没有找到,则继续通过`__proto__`查找,一直找到`Object类`的原型,若还是没有找到,则是`undefined` > 注意:通过`__proto__`查找所属类的原型,一级级往父类的原型找,就形成了原型链 `__proto__`是实现`继承`的关键 #### 原型上扩展方法 - 内置类原型上的方法可以一个一个修改,但不能批量修改 - `__proto__` IE浏览器不支持