十五、JavaScript面向对象
-
关注对象的形式进行开发,面对JavaScript中对象数据类型
-
面向对象,是一种编程思想、语法、方法、代码编写的方式
-
面向对象
-
关注注重对象的操作
-
可以设定属性/键名
-
可以设定属性值/键值
-
可以设定函数
-
-
可以将需要执行的程序内容,都定义给对象
-
调用对象的函数,来执行程序
-
-
有JavaScript提供好的内置对象,或者别人写的第三方插件
-
也可以自己自定义构造函数,创造一个工具
工厂模式:
-
以固定的模式,生成对象
-
输入参数数据,就给我们创建一个响应的对象出来
1 function createObj(n, a, s) { 2 // 创建对象 3 const obj = {}; 4 // 给对象添加属性和属性值 5 obj.name = n; 6 obj.age = a; 7 obj.sex = s; 8 // 给对象添加函数方法 9 obj.fun = function () { 10 console.log(this.name, this.age, this.sex); 11 } 12 // 返回这个对象 13 return obj; 14 } 15 16 const obj1 = createObj('张三', 18, '男'); 17 console.log(obj1);
构造函数:本质还是一个函数,是一个专门生成对象的函数,生成的这个对象,有属性属性值,还有函数方法
-
定义函数时,还是按照原始方法定义函数
-
调用函数时,必须使用 new 来配合调用函数
1 function CreateObj(n, a, s) { 2 console.log(this); 3 4 this.name = n; 5 this.age = a; 6 this.sex = s; 7 this.fun = function () { 8 console.log(this); 9 // console.log(this.name,this.age,this.sex); 10 } 11 } 12 const obj1 = new CreateObj('张三', 18, '男');
-
new 关键词会自动创建一个对象,并且会自动返回这个对象
-
与 new 一起使用的函数,不用再定义创建对象和返回值对象
-
所谓的构造函数,本质上就还是一个函数
-
为了区分构造函数和普通函数,JavaScript约定俗成
-
构造函数,函数名称 大驼峰命名法
-
普通函数,函数名称 小驼峰命名法
-
-
this指向
-
使用 function 定义的函数,this指向,看的是调用之前写的内容
-
构造函数的 this,指向的都是通过构造函数,创建的对象
-
-
构造函数的返回值,一定是一个对象,通过构造函数生成的对象,称为实例化对象
-
定义构造函数程序时,不要定义对象,不要定义return
prototype:原型
-
每一个函数天生就具有的自带的属性,叫做prototype
-
以对象的形式,存储公共的内容
-
构造函数也是函数,也有 prototype
-
实例化对象,可以直接指向调用构造函数 prototype 空间中的内容
1 // 通过公共空间 prototype 定义函数方法 2 function CreateObj(name,age){ 3 this.name = name; 4 this.age = age; 5 } 6 7 CreateObj.prototype.fun = function(){ 8 console.log(this.name,this.age); 9 } 10 11 const obj1 = new CreateObj('张三' , 18); 12 const obj2 = new CreateObj('李四' , 20);
-
__proto__: 是每个 对象 都天生就具有的属性
-
prototype:是每个 函数 都天生就具有的属性,是 对象
-
实例化对象,也是对象,只不过是通过构造函数生成的实例化对象
-
此时实例化对象 __proto__ 指向的地址就是构造函数 prototype 内存地址
-
通过 __proto__ 调用的就是构造函数 prototype 中的存储的内容
-
数据的调用和执行
-
实例化对象在调用属性和函数方法时,优先调用实例化对象本身的属性和函数方法(也就是说实例化对象中有name属性,prototype中也有name属性,优先调用实例化对象本身的name属性)
-
如果调用实例化对象本身没有的属性,会去 __proto__ 也就是构造函数prototype中找是否有这个属性
-
如果有,就调用这个属性
-
如果都没有这个属性,执行结果是undefined
-
-
如果想直接调用 __proto__ 也就是 构造函数 prototype 中定义的属性,可以使用语法,实例化对象.__proto__.属性
-
-
实际项目中,prototype中只写函数方法,不要写属性
-
prototype:原型对象
-
每一个函数,天生都具有 prototype
-
-
__proto__:原型属性
-
每一个对象,天生都具有 __proto__
-
-
JavaScript中每一种数据类型本质上都是对象类型,每一种数据类型实际上都有__proto__属性
-
每一个数据类型 / 数据,都可以通过 __proto__ 找到生成这个数据类型的 构造函数的prototype
-
构造函数,本身也有 __proto__ 可以再找这个构造函数的父级构造函数
-
最终找到的都是 JavaScript中 顶级构造函数Object(),这个过程就是所谓的原型链
1、Object.prototype.toString
精确检验数据类型的方法存储在 Object() 顶级中的方法
1 // Object.prototype.toString.call( 要检查的数据 ) 2 3 console.log(Object.prototype.toString.call(true)); // [object Boolean] 4 console.log(Object.prototype.toString.call(100)); // [object Number] 5 console.log(Object.prototype.toString.call(100.123));// [object Number] 6 console.log(Object.prototype.toString.call(1e3)); // [object Number] 7 console.log(Object.prototype.toString.call(NaN)); // [object Number] 8 console.log(Object.prototype.toString.call('sting')); // [object String] 9 console.log(Object.prototype.toString.call(undefined)); // [object Undefined] 10 console.log(Object.prototype.toString.call(null)); // [object Null] 11 console.log(Object.prototype.toString.call([])); // [object Array] 12 console.log(Object.prototype.toString.call({})); // [object Object] 13 console.log(Object.prototype.toString.call(function () { })); // [object Function] 14 console.log(Object.prototype.toString.call(new Date())); // [object Date] 15 console.log(Object.prototype.toString.call(/^\d$/)); // [object RegExp]
判断数据是否是某个具体的数据类型时,判断的字符串也必须有 [ ]
1 console.log(Object.prototype.toString.call(true) === '[object Boolean]');
2、instanceof
-
instanceof用来判断A是否为B的实例
-
instanceof检测的是原型,内部机制是通过判断对象的原型链中是否有类型的原型
1 {} instanceof Object; //true 2 [] instanceof Array; //true 3 [] instanceof Object; //true 4 "123" instanceof String; //false 5 new String(123) instanceof String; //true
3、constructor
-
当一个函数F被定义时,JS引擎会为F添加prototype原型
-
然后在prototype上添加一个constructor属性,并让其指向F的引用
-
F利用原型对象的constructor属性引用了自身
-
当F作为构造函数创建对象时,原型上的constructor属性被遗传到了新创建的对象上
-
从原型链角度讲,构造函数F就是新对象的类型
1 ''.constructor == String // true 2 new Number(1).constructor == Number // true 3 true.constructor == Bollean // true 4 new Function().constructor == Function //true 5 new Date().constructor == Date // true 6 new Error().constructor == Error // true 7 [].constructor == Array // true 8 document.constructor == HTMLDoucment // true 9 window.constructor == window //true