JavaScript复习

原型
继承得靠原型来实现。
其实原型的概念很简单:
所有对象都有一个属性 proto 指向一个对象,也就是原型
每个对象的原型都可以通过 constructor 找到构造函数,构造函数也可以通过 prototype 找到原型
所有函数都可以通过 proto 找到 Function 对象
所有对象都可以通过 proto 找到 Object 对象
对象之间通过 proto 连接起来,这样称之为原型链。当前对象上不存在的属性可以通过原型链一层层往上查找,直到顶层 Object 对象
那什么是原型呢?你可以这样理解:每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。
proto
这是每一个JavaScript对象(除了 null )都具有的一个属性,叫__proto__,这个属性会指向该对象的原型。
constructor
指向实例倒是没有,因为一个构造函数可以生成多个实例,但是原型指向构造函数倒是有的,这就要讲到第三个属性:constructor,每个原型都有一个 constructor 属性指向关联的构造函数。

类的继承
1、原型链继承,将父类的实例作为子类的原型,他的特点是实例是子类的实例也是父
类的实例,父类新增的原型方法/属性,子类都能够访问,并且原型链继承简单易于实
现,缺点是来自原型对象的所有属性被所有实例共享,无法实现多继承,无法向父类构
造函数传参。
2、构造继承,使用父类的构造函数来增强子类实例,即复制父类的实例属性给子类,
构造继承可以向父类传递参数,可以实现多继承,通过 call 多个父类对象。但是构造继承只能继承父类的实例属性和方法,不能继承原型属性和方法,无法实现函数服用,每个子类都有父类实例函数的副本,影响性能
3、实例继承,为父类实例添加新特性,作为子类实例返回,实例继承的特点是不限制
调用方法,不管是 new 子类()还是子类()返回的对象具有相同的效果,缺点是实
例是父类的实例,不是子类的实例,不支持多继承
4、拷贝继承:特点:支持多继承,缺点:效率较低,内存占用高(因为要拷贝父类的
属性)无法获取父类不可枚举的方法(不可枚举方法,不能使用 for in 访问到)
5、组合继承:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父
类实例作为子类原型,实现函数复用
6、寄生组合继承:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构
造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点

 JS 中的垃圾回收机制
参考回答:
必要性:由于字符串、对象和数组没有固定大小,所有当他们的大小已知时,才能对他
们进行动态的存储分配。JavaScript 程序每次创建字符串、数组或对象时,解释器都必
须分配内存来存储那个实体。只要像这样动态地分配了内存,最终都要释放这些内存以
便他们能够被再用,否则,JavaScript 的解释器将会消耗完系统中所有可用的内存,造
成系统崩溃。
这段话解释了为什么需要系统需要垃圾回收,JS 不像 C/C++,他有自己的一套垃圾回收
机制(
Garbage Collection)。JavaScript 的解释器可以检测到何时程序不再使用一个对象
了,当他确定了一个对象是无用的时候,他就知道不再需要这个对象,可以把它所占用
的内存释放掉了。例如:
64var a=“hello world”;
var b=“world”;
var a=b;
//这时,会释放掉"hello world",释放内存以便再引用
垃圾回收的方法:标记清除、计数引用。
标记清除
这是最常见的垃圾回收方式,当变量进入环境时,就标记这个变量为”进入环境“
,从逻
辑上讲,永远不能释放进入环境的变量所占的内存,永远不能释放进入环境变量所占用
的内存,只要执行流程进入相应的环境,就可能用到他们。当离开环境时,就标记为离
开环境。
垃圾回收器在运行的时候会给存储在内存中的变量都加上标记(所有都加),然后去掉
环境变量中的变量,以及被环境变量中的变量所引用的变量(条件性去除标记),删除
所有被标记的变量,删除的变量无法在环境变量中被访问所以会被删除,最后垃圾回收
器,完成了内存的清除工作,并回收他们所占用的内存。
引用计数法
另一种不太常见的方法就是引用计数法,引用计数法的意思就是每个值没引用的次数,
当声明了一个变量,并用一个引用类型的值赋值给改变量,则这个值的引用次数为 1,;
相反的,如果包含了对这个值引用的变量又取得了另外一个值,则原先的引用值引用次
数就减 1,当这个值的引用次数为 0 的时候,说明没有办法再访问这个值了,因此就把
所占的内存给回收进来,这样垃圾收集器再次运行的时候,就会释放引用次数为 0 的这
些值。
用引用计数法会存在内存泄露,下面来看原因:
function problem() {
var objA = new Object();
var objB = new Object();
objA.someOtherObject = objB;
objB.anotherObject = objA;
}
在这个例子里面,objA 和 objB 通过各自的属性相互引用,这样的话,两个对象的引用
次数都为 2,在采用引用计数的策略中,由于函数执行之后,这两个对象都离开了作用
域,函数执行完成之后,因为计数不为 0,这样的相互引用如果大量存在就会导致内存
泄露。
特别是在 DOM 对象中,也容易存在这种问题:
var element=document.getElementById(’‘);
var myObj=new Object();
myObj.element=element;
element.someObject=myObj;
这样就不会有垃圾回收的过程。

闭包 (有什么用)
参考回答:
(1)什么是闭包:
闭包是指有权访问另外一个函数作用域中的变量的函数。
闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。闭包就是
就是函数的“堆栈”在函数返回后并不释放,我们也可以理解为这些函数堆栈并不在栈
上分配而是在堆上分配。当在一个函数内定义另外一个函数就会产生闭包。
(2)为什么要用:
匿名自执行函数:我们知道所有的变量,如果不加上 var 关键字,则默认的会添加到全
局对象的属性上去,这样的临时变量加入全局对象有很多坏处,比如:别的函数可能误
用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链
上遍历的)。除了每次使用变量都是用 var 关键字外,我们在实际情况下经常遇到这样一
种情况,即有的函数只需要执行一次,其内部变量无需维护,可以用闭包。
结果缓存:我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,
每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函
数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如
果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部
的引用,从而函数内部的值可以得以保留。
封装:实现类和继承等。

this 的指向 哪几种
参考回答:
默认绑定:全局环境中,this 默认绑定到 window。
隐式绑定:一般地,被直接对象所包含的函数调用时,也称为方法调用,this 隐式绑定到该直接对象。
隐式丢失:隐式丢失是指被隐式绑定的函数丢失绑定对象,从而默认绑定到 window。显式绑定:通过 call()、apply()、bind()方法把对象绑定到 this 上,叫做显式绑定。
new 绑定:如果函数或者方法调用之前带有关键字 new,它就构成构造函数调用。对于
this 绑定来说,称为 new 绑定。
【1】构造函数通常不使用 return 关键字,它们通常初始化新对象,当构造函数的函数 体执行完毕时,它会显式返回。在这种情况下,构造函数调用表达式的计算结果就是这个新对象的值。
【2】如果构造函数使用 return 语句但没有指定返回值,或者返回一个原始值,那么这 时将忽略返回值,同时使用这个新对象作为调用结果。
【3】如果构造函数显式地使用 return 语句返回一个对象,那么调用表达式的值就是这 个对象。

call 和 apply 是用来做什么?
参考回答:
106Call 和 apply 的作用是一模一样的,只是传参的形式有区别而已
1、改变 this 的指向
2、借用别的对象的方法,
3、调用函数,因为 apply,call 方法会使函数立即执行

typeof 实现原理
typeof 一般被用于判断一个变量的类型,我们可以利用 typeof 来判断number, string, object, boolean, function, undefined, symbol 这七种类型,这种判断能帮助我们搞定一些问题,比如在判断不是 object 类型的数据的时候,typeof能比较清楚的告诉我们具体是哪一类的类型。但是,很遗憾的一点是,typeof 在判断一个 object的数据的时候只能告诉我们这个数据是 object, 而不能细致的具体到是哪一种 object, 比如
let s = new String(‘abc’);
typeof s === ‘object’// true
s instanceof String // true

简单来说,我们使用 typeof 来判断基本数据类型是 ok 的,不过需要注意当用 typeof 来判断 null 类型时的问题,如果想要判断一个对象的具体类型可以考虑用 instanceof,但是 instanceof 也可能判断不准确,比如一个数组,他可以被 instanceof 判断为 Object。所以我们要想比较准确的判断对象实例的类型时,可以采取 Object.prototype.toString.call 方法。

bind,apply,call
参考回答:
apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A,
arguments);即 A 对象应用 B 对象的方法。
call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);
即 A 对象调用 B 对象的方法。
bind 除了返回是函数以外,它的参数和 call 一样。

bind 和 apply 的区别
参考回答:
返回不同:bind 返回是函数
参数不同:apply(A, arguments),bind(A, args1,args2)

柯里化
在数学和计算机科学中,柯里化是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值