js红宝书学习记录4-6
两个垃圾清除策略
1.标记清除
运行时标记所有变量,(书中提到了使用位作为标记去记录变量进入还是离开了环境,这一点类似于操作系统中的位图法),然后去除环境中的变量和环境中被变量引用(闭包的起因!!)的标记。之后再被标记的变量都是可清除变量,定时清理。
2.引用计数
跟踪记录每个值被引用的次数。这个跟文件系统的硬链接数有点类似。
function f(){
var objectA=new Object();
var objectB=new Object();
objectA.a=objectB;// objectB的引用次数为1
objectA.b=objectB;// objectB的引用次数为2
objectA.a=1// objectB的引用次数为1
}
定时清除引用次数为0的值,但是他会有很严重的一个问题,那就是循环引用问题!!顾名思义,A的属性赋值了B,B的属性赋值了A。。。重大缺陷导致了js基本都是第一种策略了。顺带提一下IE8以前的BOM和DOM都是这种策略(基于c++编写的COM对象实现的,第一次听到浏览器还有c++。是我低估了它了)
正则表达式的方法
- exec(),返回匹配项第一个匹配项,全局模式下再次执行会从上一次匹配位置开始往后匹配,到末尾时返回null,下次从头匹配
- test(),匹配成功返回true,反之相反
消除递归函数的紧密耦合:arguments.callee
apply()(第二参数:数组)和call()(参数列举出来):在特定的作用域中调用函数,但是他们真正强大的地方是扩大作用域。(具体就不说了,有很多博客都写了)
bind():es5新增方法,创建函数实例,其this值传给bind()函数的值。
var a=b.bind(c);// bd的this指针现在指向c了
基本包装类型的概念:读取基本类型时,会创建一个对应的基本包装类型的对象,从而让我们能够调用方法(如:‘a’.split(),方法调用完毕后对象将会被销毁)
ECMA中有两种属性:(这里的属性是指对象的属性特性)
1.数据属性:
[[Configurable]]:能否通过delete删除属性从而重新定义属性;赋值False后,只能修改Writable
[[Enumerable]]:能够for-in
[[Writable]]:能否修改
[[Value]]:属性的数据值
var person={name:1}// 此时name属性的前三数据属性都为true,Value为1
Object.defineProperty(person,"age",{})// 此时age属性的前三数据属性都为false,Value为undefined
Object.defineProperty(属性所在对象,属性名,{四种数据属性:值})可以修改属性特性。(出现了,vue双向数据绑定的根源,具体后面要不要整理)
2.访问器属性:
[[Configurable]]:能否通过delete删除属性从而重新定义属性;赋值False后,只能修改Writable
[[Enumerable]]:能够for-in
[[Get]]:读值函数
[[Set]]:写值函数
var book={
_year:2004,
edition:1
}
Object.defineProperty(book,"year",{
get:()=>this._year,
set:function (newValue){
if(newValue>2004){
this._year=newValue;
this.edition += newValue-2004
}
}})//前两个值没定义,默认为false
book.year=2005;
=>2005
book.edition// 被更改了,数据绑定了
=>2
book._year //被更改了,数据绑定了
=>2005
使用Object.getOwnPropertyDescriptor()方法即可访问属性的特性。
Object.getprototypeOf():返回原型
Object.hasOwnProperty():检测属性处于原型(false)还是实例(true)
Object.keys():获取所有可枚举实例属性的字符串数组
Object.getOwnPropertyNames():获取所有实例属性的字符串数组(包括不可枚举如:constructor,设置[[Enumerable]]为false的属性)
new操作符的四个步骤(面试):
- 创建一个新的对象
- 将构造函数的作用域赋值给新对象(this指向新对象)
- 执行构造函数中的代码(添加属性)
- 返回新对象
面试老话题,不多讲,反而我想问下,那如果我不用new操作符呢?此时的构造函数会怎么样呢?
为什么有这个疑问,是因为在书上看到了一个例子,一个概念:
稳妥构造函数
构建一个没有公共属性,而且其方法也不引用this的对象。
const a=(name,age,job)=>{var o=new Object();var _sex="男";o.getName=()=>{console.log(name)};return o;}
=>undefined
var test=a('he',29,"driver");
=>undefined
test.getName()//获取到了
=>'he'
test._sex//私有变量,不允许访问,其实该变量也早已经销毁,至于在暴露出来的getName()处使用了私有变量,那就是一个经典的闭包了,第七章再说
=>undefined
可以看到,不是用new操作符的话,如果没有return值的话,作用域内的变量其实在执行完后已经全部销毁了。若是返会对象的话,也只是返回对象上的属性,不包括作用域内的属性。
js继承
不多复述,网上都有
-
原型链继承
缺点:实例共享原型上的属性方法
-
构造继承
function SubType(){ SuperType.call(this,...)//调用超类构造函数 this...//定义子类属性,方法 }
缺点:方法在构造函数中定义,函数复用无从谈起
-
原型链构造组合继承
缺点:调用两次超类构造函数
-
原型式继承
Object.create()
-
寄生式继承
-
寄生组合式继承