JS构造函数
- 当你感觉晚的时候 正是开始的最佳时机 加油
1.构造函数的模式基础:品牌概念
- 品牌概念(如培训机构是一个类 比较有名的有珠峰 千峰 达内 构造函数就为了实现不同的品牌细分)
- 万物皆对象
- 类: 对象的具体细分
- 实例: 类当中的具体事务
//数组内置类: Array 每一个数组都是数组内置类的实例
//对象内置类: Object 每一个对象数据类型都是对象内置类的实例
//函数内置类: Function 每一个函数都是函数内置类的实例
//Js中除了内置类 项目中也需要自定义类
2.温习工厂模式(函数模式)
function createJsPerson() {
var obj = {};
obj.name = name;
obj.writeJs = function() {
console.log("my name is " + this.name + ",i can write js la");
}
return obj;
}
var p1 = createJsPerson("A",18);
p1.wrireJs();
//p1 是对象数据类型的 createJsPerson 是函数名 方法名
//通过函数的执行 返回一个对象
3.构造函数(主要看和工厂模式的区别)
- 构造函数模式的目的就是为了创建一个自定义类,并且创建这个类的实例
function CreateJsPerson(name,age) {
this.name = name;
this.age = age;
this.writeJs = function() {
console.log("my name is " + this.name + ",i can write js la");
}
}
//不用再定义obj 也不用再return obj
var p2 = new CreateJsPerson("A",18);// CreateJsPerson就是类
p2.writeJs();
- 构造函数模式和工厂模式的区别
1、执行的时候 普通函数执行(工厂模式) ---> createJsPerson() 构造函数模式 ---> new CreateJsPerson() 通过new执行后,我们的CreateJsPerson就是一个类了(为了和内置类有一样的标准,首字母建议大写),而函数执行的返回值P2就是CreateJsPerson这个类的一个实例
- 扩展
//创建一个数组
var array = [] //字面量方式
var array = new Array();//实例创建的方式 ---> 构造函数模式执行的方式
//不管哪一种方式创建数组 array都是Array这个类的一个实例
- JS中所有的类都是函数数据类型的 它通过new执行变成一个类,但是它本身也是一个普通的函数
- JS中所有的实例都是对象数据类型的
- typeOf P2 "object" 类型
- typeOf CreateJsPerson "function" 类型
2、在函数代码执行的时候 相同:都是形成一个私有的作用域,然后形参赋值 -->预解释 --> 代码从上往下执行(类也有普通函数的一面) 不同:在代码执行之前,构造函数不用再自己创建对象,浏览器会默认创建一个对象数据类型的值(这个对象其实就是我们当前类的一个实例),然后代码从上往下执行,以当前实例为执行的主体(this就是当前的实例),然后分别把属性名和属性值赋给当前实例
function CreateJsPerson(name,age) {
this.name = name; //---> this代表当前隐形的对象
this.age = age;
this.writeJs = function() {
console.log("my name is " + this.name + ",i can write js la"); //this ---> p1 代表当前实例
}
// 把属性名和属性值赋值给当前实例 不用再定义obj 也不用return obj
}
var p1 = new CreateJsPerson("A",18);
p1.writeJs();
3、this的第4点 在构造函数模式中,类中(函数体中)出现的this.xxx = xxx中的this是当前类的一个实例
4、虽然p1和p2都是CreateJsPerson 这个类的实例,所以都拥有writeJs这个方法,但是不同实例之间的方法是不一样的
- console.log(p1.writeJs === p2.writeJs)// false
- 在类中给实例增加属性(this.xxx = xxx),属于当前实例的私有属性,实例和实例之间是单独的个体,所以私有的属性之间是不相等的
5、var res = CreateJsPerson("B",19);
- 这样不是构造函数执行,而是普通函数的执行 由于没有return,所以res = undefined
- 并且CreateJsPerson这个方法中的this就是window
4.构造函数的扩展
function Fn() {
var num = 100;
this.x = 100;
this.getX = function() {
console.log(this.x);
}
}
var f1 = new Fn;
var f2 = new Fn;
-
在构造函数模式中,new Fn()执行,如果Fn不需要传递参数的话,后面的小括号可以省略
-
this问题,在类中出现的this.xxx = xxx;中的this都是当前类的一个实例
-
而某一个属性值(方法),方法中的this需要看方法执行的时候,前面是否有"." 才知道this是谁,
-
f1.getX() ---> this指f1,输出100
-
var ss = f1.getX(); ss() ---> this 指window --->输出undefined
-
console.log(f1.num) // --->输出undefined
-
类有普通函数的一面,当函数执行的时候,var num 其实只是当前形式的私有作用域中的私有变量而已,它和我们的f1这个实例没有任何关系,只有this.xxx = xxx才相当于给f1这个实例增加私有的属性和方法,才和我们的f1有关系
-
在构造函数模式中,浏览器会默认把我们的实例返回,返回的是一个对象数据类型的值,如果我们自己加了return语句,返回的是一个基本数据类型的值,当前实例是不变的,例如return 100;我们的f1还是当前Fn类的实例,如果返回的是一个引用类型的值,当前实例会被自己返回的值给替换掉,例如return { name: 100},我们的f1就不再是fn的实例了,而是对象 {name:100}
-
检测某一个实例是否属于这个类,--->instanceof console.log(f1 instanceof Fn) //true console.log(f1 instanceof object) //true
-
因为所有的实例都是对象数据类型的,而且每一个对象的数据类型都是object这个内置类的一个实例,所以f1也是它的一个实例
-
对于检测数据类型来说,typeof有自己的局限性,不能细分object下的对象、数组、正则 。。。。。
-
var a = [];console.log(a instanceof Array) //true 说明a是一个数组
-
f1和f2都是fn这个类的一个实例,都拥有x和getX两个属性,但是这两个属性都是各自的私有属性,所以console.log(f1.getX === f2.getX) //false
-
"in" 检测某一属性是否属于这个对象,attr in Object,console.log("getX" in f1);//true getX是f1的一个私有属性
-
(attr in object) 不管是私有属性还是共有属性,只要存在,用in来检测都是ture
-
hasOwnProperty:用来检测某一个属性是否为这个对象的"私有属性",这个方法只能检测私有的属性 console.log(f1.hasOwnProperty("getX") )//true 因为getX是f1的私有属性
-
扩展思考:检测某一个属性是否为对象的"公有属性"
function hasPubProperty() {
return (attr in obj) && !obj.hasOwnProperty(attr)
//首先 保证是它的一个属性 并且还不是私有属性 那么只能是公有的属性了
}