JS构造函数的原型以及继承方法
JavaScript高级
重点:
一、构造函数和原型、
1、构造函数
(1)构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 一起使用。
我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
(2)new 在执行时会做四件事情:
① 在内存中创建一个新的空对象。
② 让 this 指向这个新的对象。
③ 执行构造函数里面的代码,给这个新对象添加属性和方法。
④ 返回这个新对象(所以构造函数里面不需要 return )。
2、静态成员和实例成员
(1)实例成员
实例成员就是构造函数内部通过this添加的成员,实例成员只能通过实例化的对象来访
(2)静态成员
静态成员 在构造函数本身上添加的成员,静态成员只能通过构造函数来访问
3、构造函数原型对象prototype
(1)构造函数方法很好用,但是存在浪费内存的问题-- 实例化构造函数调用里面函数,会为函数开辟单独的内存空间
(2)原型对象实现共享:公共属性定义到构造函数里面, 公共的方法我们放到原型对象身上。
(3)JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象。
注意这个 prototype 就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。
4、对象原型__proto__
(1)对象都会有一个属性 proto 指向构造函数的 prototype 原型对象, 之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 proto 原型的存在。
(2)__proto__对象原型和原型对象 prototype 是等价的
(3)__proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象 prototype
5、原型constructor构造函数
(1)对象原型( proto)和构造函数(prototype)原型对象里面都有一个属性 constructor 属性,我们称为构造函数,它指回构造函数本身。 **
(2)constructor 作用 -- 记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。**
(3)一般情况下,对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了。此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。
注:如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数
(4)__proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象 prototype
6、利用原型 -- 扩展数组类(Array)的功能:
(1)为每一个数组对象添加一个方法,可以查找某个元素的所在位置
(2)调用find方法返回参数在数组中出现的位置
7、原型链
每一个实例对象又有一个proto属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有proto属性,这样一层一层往上找就形成了原型链。
8、构造函数实例和原型对象三角关系
(1)构造函数的prototype属性指向了构造函数原型对象
(2)实例对象是由构造函数创建的,实例对象的__proto__属性指向了构造函数的原型对象
(3)构造函数的原型对象的constructor属性指向了构造函数,实例对象的原型的constructor属性也指向了构造函数
9、原型链和成员的查找机制
(1)当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
(2)如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)。
(3)如果还没有就查找原型对象的原型(Object的原型对象)。
(4)依此类推一直找到 Object 为止(null)
(5)__proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线。
10、原型对象中this指向
构造函数中的this和原型对象的this,都指向我们new出来的实例对象
11、扩展内置对象
可以通过原型对象,对原来的内置对象进行扩展自定义的方法。比如给数组增加自定义求偶数和的功能。
注意:数组和字符串内置对象不能给原型对象覆盖操作 Array.prototype = {} ,只能是 Array.prototype.xxx = function(){} 的方式。
二 、继承
ES6之前并没有给我们提供 extends 继承。我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承。
1、call()
(1)call()可以调用函数
(2)call()可以修改this的指向,使用call()的时候 参数一是修改后的this指向,参数2,参数3..使用逗号隔开连接
2、借用构造函数继承父类型属性
核心原理: 通过 call() 把父类型的 this 指向子类型的 this ,这样就可以实现子类型继承父类型的属性。
(1)先定义一个父构造函数
(2)再定义一个子构造函数
(3)子构造函数继承父构造函数的属性(使用call方法)
3、借用原型对象继承父类型方法
一般情况下,对象的方法都在构造函数的原型对象中设置,通过构造函数无法继承父类方法。
核心原理:
① 将子类所共享的方法提取出来,让子类的 prototype 原型对象 = new 父类()
② 本质:子类原型对象等于是实例化父类,因为父类实例化之后另外开辟空间,就不会影响原来父类原型对象
③ 将子类的 constructor 从新指向子类的构造函数
三、ES5新增方法
1、数组方法forEach遍历数组
arr.forEach(function(value, index, array){}
参数一是:数组元素
参数二是:数组元素的索引
参数三是:当前的数组
2、数组方法filter过滤数组
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素,主要用于筛选数组
注意它直接返回一个新数组
参数一是:数组元素
参数二是:数组元素的索引
参数三是:当前的数组
3、数组方法some
some 查找数组中是否有满足条件的元素
注意它返回值是布尔值, 如果查找到这个元素, 就返回true , 如果查找不到就返回false.
特点:如果找到第一个满足条件的元素,就终止循环. 不在继续迭代查找。
参数一是:数组元素
参数二是:数组元素的索引
参数三是:当前的数组
4、map()方法
(1)map()方法定义在JavaScript的Array中,它返回新的数组,新数组中的值,为原始数组调用函数处理后的值。
(2)map()不会对空数组进行检测
(3)map()不会改变原始数组
5、every() 方法
(1)every() 方法用于检测数组所有元素是否都符合指定条件(筛选)。
(2)every() 不会对空数组进行检测。
(3)every() 不会改变原始数组。
(4)如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。如果所有元素都满足条件,则返回 true 。
6、筛选商品案例
7、some和forEach区别
(1)如果查询数组中唯一的元素, 用some方法更合适,在some 里面 遇到 return true 就是终止遍历 迭代效率更高
(2)在forEach 里面 return 不会终止迭代
8、trim方法去除字符串两端的空格
(1)trim方法只能去除字符串两端的空格 -- 不会去除中间的。
(2)返回值 --- 一个新的字符串。
9、获取对象的属性名
Object.keys(对象) 获取到当前对象中的属性名 ,返回值是一个数组
10、设置或修改对象中的属性
Object.defineProperty设置或修改对象中的属性
(1)writable如果值为false 不允许修改这个属性值
(2)enumerable 如果值为false 则不允许遍历
(3)configurable 如果为false 则不允许删除这个属性 属性是否可以被删除或是否可以再次修改特性
有关对象与类,类的创建、添加与继承请点击a=href"https://www.cnblogs.com/kk199578/p/14209148.html"