目录
一、面向对象
1. 继承
只要将方法定义放在构造函数中,那么每次 new 时都会执行 function,这样就会反复创建相同函数的多个副本,导致浪费内存。如果将来发现多个子对象都要使用相同的功能和属性值时,都可以用继承来解决。
父对象中的成员,子对象无需重复创建就可直接使用,就像使用自己的成员一样,这就是继承。js 中的继承都是通过原型对象实现的,原型对象就是替所有子对象集中保存共有属性值和方法的特殊父对象。当多个子对象需要使用相同的功能和属性值时,都可将相同的功能和属性值集中定义在原型对象中。
原型对象不用自己创建,在定义构造函数时,程序自动附赠我们一个空的原型对象。构造函数中都有一个自带的属性 prototype,指向自己配对的原型对象——构造函数 .prototype。
| 补充:new的四个作用 |
| 1. 创建一个新的空对象等待 |
| 2. 让子对象继承构造函数的原型对象(继承专用) |
| 3. 调用构造函数,将this替换为新对象,通过强行赋值方式为新对象添加规定的属性 |
| 4. 返回新对象地址 |
new 的第二步自动让新创建的子对象,继承构造函数的原型对象。new 会自动为子对象添加_ _proto_ _ 属性,指向构造函数的原型对象。
向原型对象中添加新的共有属性和方法时,只能是强行赋值:
|
构造函数.prototype.共有方法=function(){ … } |
| 构造函数.prototype.共有属性=属性值 |
添加新属性或方法后,用子对象访问对象的成员时,js引擎先在子对象内部查找自有的属性;如果子对象没有,则 js 引擎会自动延 _ _proto_ _ 属性去父元素查找。如果在父元素中找到了想要的属性或方法,则和访问子对象的方法一样调用。
示例: 将所有子对象共用的方法保存进构造函数里
自有属性和共有属性
| 自有属性:保存在子对象内部,只归当前子对象自有的属性; |
| 共有属性:保存在父对象(原型对象)中,归多个子对象共有的属性; |
(1)获取属性值时,毫无差别,都可用: 子对象.属性名。如果 js 引擎发现要使用的属性不在子对象中,则自动延 _ _proto_ _ 属性向父对象继续查找要用属性。
(2)修改属性值
| 自有属性: | 子对象.属性名=属性值; |
| 共有属性: | 正确方法 | 错误方法 |
| 构造函数.prototype.共有属性=新值 | 子对象.共有属性=新值 | |
| 共有属性,必须用原型对象修改 | 此方法不但不会修改原型对象中的共有属性,而且还会给当前子对象添加一个同名的自有属性。从此,这个子对象,在这个属性的使用上,与其他子对象,再无法保持同步! |
示例: 为所有学生添加共有的班级名属性,并修改;
内置类型的原型对象
内置类型就是 ES 标准中规定的,浏览器已经实现,我们可以直接使用的类型。包括十一种String、Number、Boolean、Array、Date、RegExp、Error、Function、Object、Math(不是类型,而是一个{ }对象)、global(全局作用域对象,在浏览器中被window代替)。
每种类型一定有2部分组成:构造函数,负责创建该类型的子对象;原型对象,负责为该类型所有子对象集中保存共有的属性值和方法定义。除 Math 和 global 之外,其余也都可以通过 new 创建子对象。
想要查看该类型中有哪些 API,可以使用 — 类型名.prototype — 。

如果经常使用的一个功能,但是原型对象中没有提供,我们可以自定义一个函数保存到原型对象中。
| 构造函数.prototype.新方法=function(){…} |
举例:为数组类型添加求和的方法
原型链
原型链是由多级父对象逐级继承形成的链式结构,保存着:一个对象可用的所有属性和方法,控制着属性和方法的使用顺序,采用就近原则,先子级后父级。
2. 多态
多态指同一个函数,在不同情况下表现出不同的状态,包括重载和重写。
|
重载overload |
同一个函数,输入不同的参数,执行不同的逻辑。 |
| 重写override | 在子对象中定义一个和父对象中的成员同名的自有成员。当从父对象继承来的个别成员不好用时,就可以在子对象中定义同名成员,来覆盖父对象中的同名成员。 |
3. 自定义继承
(1)只更换一个对象的父对象,两种方法:
| 子对象._ _proto_ _=新父对象 | 不推荐 |
| Object.setPrototypeOf(子对象, 新父对象) | 推荐 |
//示例:更换一个对象的父对象
(2)批量更换多个子对象的父对象,只需要更换构造函数的 prototype 属性就可以,但必须在创建子对象之前更换!
//示例: 批量更换两个子对象的父对象
二、ES5(ECMAScript 第5个版本)
1. 严格模式
在旧的js中有很多广受诟病的缺陷,严格模式就是比旧的js运行机制要求更严格的新运行机制,今后企业中所有代码都要运行在严格模式下。启用严格模式只需在当前代码段的顶部添加: "use strict"; 即可。
严格模式有四个新规定:
a:禁止给未声明过的变量赋值;旧的js中,如果强行给未声明过的变量赋值,不会报错,而是,自动在全局设置该变量,这就造成了全局污染。而严格模式中,强行给未声明过的变量赋值,会报错,这样就减少了因为写错变量名造成的全局污染!
举例:给未声明的局部变量赋值
未使用严格模式,打印如下,本来想给“女朋友”发送的消息,却发到了全局,但系统不报错。

启用严格模式,在代码段首行添加"use strict";
打印如下,此时直接报错,便于我们发现程序中的问题并修改。

b. 静默失败升级为错误;静默失败指程序运行不成功,但是也不报错,这样极其不利于调试程序,严格模式:会将绝大部分静默失败都升级为报错。
打印如下:即使将eid设置为只读,属性值仍被修改,但不报错。

启动严格模式后打印如下:

c. 普通函数调用中的 this 不再指 window,而是指 undefined,在旧 js 中普通函数调用中的 this 默认指 window,极容易造成全局污染。启用严格模式后普通函数调用中的 this 指向 undefined,不再指 window,可防止因为错误使用 this 而导致的全局污染。
d. 禁用了 arguments.callee,arguments.callee; 是在一个函数内,获得当前函数本身的一种特殊关键字(递归)。在函数内写死当前函数名,一旦外部函数名改变,内部函数名忘记修改,则程序立刻报错造成紧耦合,所以在函数内使用 arguments.callee 代替写死的函数名。在运行时,自动获得当前函数本身(松耦合)。
而且递归重复计算量太大,效率极低,如果递归调用严重影响程序的性能时,就要用循环来代替递归。举例:分别使用递归和循环实现计算斐波那契数列第 n 个数
//递归方式
//循环方式
补充:this 4种指向;
(1)obj.fun() fun中的this指 .前的obj对象(谁调用指谁);
(2)new Fun() Fun中的this指new创建的新对象;
(3)fun() 或 (function(){ ... })() 或 回调函数 thisz默认指windozw;
(4)原型对象(prototype)中的this指将来调用这个共有函数的.前的某个子对象(谁调用指谁)。
往期JavaScript高级博文链接:
JavaScript高级(一)
JavaScript高级(二)
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/209295.html原文链接:https://javaforall.net
