工厂模式虽然实现了批量生产,但是不能进行品牌的区分-->"实例识别"
对象:一个泛指,js中万物皆对象
类:对象的一个具体的细分
实例:类中一个具体的事物
例如:自然界中万物皆对象,我们把自然中的事物分为了几大类:人类、动物类、植物类...而每一个人都是我们人类中的一个实例
我们想学习js,我们需要给js分类,然后在研究每一个类别中具体的东西-->面向对象的编程思想
所有的编程语言都是面向对象开发的-->js也是一门轻量级的脚本编程语言
面向对象开发-->研究 类的继承、封装、多态
js中的类:内置类(浏览器天生自带的)、自定义类
内置类:
Object(对象类)、Array(数组类)、RegExp(正则类)、Date、Math、Number(数字类)、String(字符串类)、Boolean(布尔类)、Function(函数类)、Null、Undefined
每一个对象数据类型都是Object这个类的一个实例,每一个数组都是数组类的实例,每一个字符串都是String这个类的一个实例......
可以在控制台console.dir(Array.prototype); 就可以清晰地看到Array上的方法,方便我们学习
HTMLColle ction(元素集合类)-->包含获取的所有的元素,它是一个类数组,我们通过getElementsByTagName、getElementsByClassName等获取的元素结合都是这个类的一个实例
console.dir(document.getElementsByTagName("div"));
console.dir(document.getElementsByClassName(".w"));
NodeList(节点集合类)-->获取的节点集合(类数组),都是这个类的一个实例
console.dir(document.getElementsByName("zhufeng"));
CSSStyleDeclaration(元素的行内样式集合类)
通过元素的style获取的样式集合都是这个类的一个实例
HTMLDivElement(div元素标签类)-->每一个HTML标签都一个自己对应的类
HTMLElement、Element、Node、EventTarget、Document、Window....
console.dir(document.getElementById("div1"));
自定义类:自己想创建一个类,需要如何的处理?--->构造函数模式
function Fn() { var a = 12; this.b = 13; this.c = function () { console.log(14); } } var f1 = new Fn(); //f1是Fn的一个实例
此时, Fn就是一个自定义类
使用构造函数模式来创建自定义类-->构造函数和普通函数的区别?
1、普通的函数的名字遵循驼峰命名法,构造函数的名字我们一般都让第一个单词首字母大写(约定俗成的一个技巧,但是不是强制的)
2、在执行的时候,普通函数createPerson("A小伙伴",7);,但是构造函数模式执行不一样了var p1=new CreatePerson("A小伙伴",7);
通过new执行的我们称之为构造函数模式,此时CreatePerson就不叫做函数名了而叫做类(CreatePerson类)-->类是函数数据类型的
通过构造函数执行返回的结果叫做当前类的一个实例,例如:p1就是CreatePerson类的一个实例-->实例是对象数据类型的
3、在作用域中运行的时候
构造函数模式执行和普通函数执行一样,都会形成一个私有的作用域,里面首先给形参赋值,然后在预解释,JS代码从上到下执行-->构造函数也有普通函数的一面
1)在构造函数模式中,我们不需要手动的创建对象(也不需要手动的返回,工厂模式是需要手动创建和返回的),浏览器会默认的创建一个对象(并且当代码执行完成后自动返回)
2)然后JS代码开始从上到下执行,在执行的过程中,我们把对应的属性和方法,分别的添加给我们浏览器自己创建的那个对象,并且函数中以这个对象为执行的主体(this)
浏览器默认创建的那个对象数据类型的数据,其实就是我们当前类的一个实例,而函数中的this也是当前类的一个实例-->只有this.xxx=xxx才是相当于给当前的实例增加属性和方法
function CreatePerson(name, age) {
age = age || 25;
var index = 3;//index是私有作用域中的一个私有的变量,和当前的实例没有任何的关系
this.name = name;//这样才相当于给我们的实例增加了属性name
this.age = age;
this.say = function () {
console.log("my name is " + this.name + "~ my age is " + this.age + "~ i can say chinese~");
};
//return 100;
//return {name:"哈哈"};
//浏览器会把默认创建的实例对象返回,如果我们手动加了return:
//1)返回的是基本数据类型值,对最后的实例没有影响
//2)返回的是引用数据类型值,会把默认返回的实例对象覆盖掉,返回的就不是当前类的实例了,p1就不在是CreatePerson的实例了
}
var p1 = new CreatePerson("A小伙伴", 7);
//console.log(p1.name);//"A小伙伴"
//console.log(p1.index);//undefined
var p2 = new CreatePerson;//在不传第参数的情况下,可以把()省略
注意:
一、类是函数数据类型的,而它的实例是对象数据类型
console.log(typeof CreatePerson);//->"function"
console.log(typeof p1);//->"object"
二、检测某一个实例是否属于这个类 instanceof
console.log(p1 instanceof CreatePerson);//->true
console.log(p1 instanceof Object);//->true p1也是一个对象数据类型的值,所以它也是Object这个类的一个实例
console.log(p1 instanceof Array);//->false
三、JS中提供了hasOwnProperty用来检测某一个属性是否是这个对象的私有属性
in:检测某一个属性是否属于这个对象(既可以检测私有的属性,也可以检测公有的属性)
console.log(p1.hasOwnProperty("say"));//-->true
console.log("say" in p1);//-->true
自己编写一个方法实现:检测某一个属性attr是否为obj这个对象的公有属性
function myHasPubProperty(attr, obj) {
return (attr in obj) && !(obj.hasOwnProperty(attr));
}