第一部分
第2章
- 什么是词法作用域?动态作用域?js所采用的作用域模型是哪种?
首先什么是作用域,简单来说就是限定一段代码的作用范围,词法作用域就是作用域是由你在写代码声明时决定的,动态作用域则是由调用时决定的.js采用的是词法作用域 - 欺骗词法方式有?
eval,with
第3章
- 什么是函数作用域?块级作用域?
在js的es6之前,大多数情况下只有两种作用域,函数作用域和全局作用域,就是在一个函数function里面会产生一个作用域.块级作用域则是在{...},在es6出现了块级作用域. - 函数中作用域有什么用?
函数中的作用域可以使内容私有化,规避冲突,外部无法访问 - 匿名函数和具名函数有啥区别?
匿名函数可读性差,调试困难,引用自身比较麻烦(类似在递归里) - 只有函数作用域会带来一些什么问题?
比较明显的类似if语句,在if语句里面申明一个变量,会导致变量声明的提示,污染全局
if(false){
var a = 2;
}
console.log(a); //undefined 不是a is not defined,
//不管if是否执行,var a都会提升到作用域的最顶端,一不小心很容易出问题
for (var i = 0; i < 5; i++) {}
console.log(i);//5 这种也会造成一定程度的内存泄漏和全局污染
- let,const作用?
提供块级作用域,声明变量不会提示,同一个作用域内不能多次声明 - 在es6前如何制造块级作用域?
可以利用try catch
try{
throw undefined
}catch (a){
a = 2;
console.log(a); //2
}
console.log(a);//a is not defined
- 什么是变量声明的提升?
在es5里函数声明和变量声明都会提升到当前作用域的顶端,其中函数声明的优先级会高于变量声明,如果函数声明的名字和变量一样,不管顺序如何,函数的声明会覆盖变量的声明 - 什么是闭包?
好像到今天,我才真正懂什么是闭包,闭包不是什么特别牛逼的东西,大致来说就是一个函数里面的子函数能访问父函数里面的变量,本质上就是外部函数和内部函数连接的桥梁.
function a() {
var num = 1;
function b() {
console.log(num);//这种现象就是闭包
}
}
function a() {
var num = 1;
function b() {
console.log(num);//这就是闭包
}
return b
}
var b = a();
b(); //2,这里就是利用闭包的特性获取到里面
console.log(num);//num is not defined
- IIFE自执行函数是什么?
(function(){})(),其实和声明一个变量赋值要执行的函数再执行是一样的
(function () {
var a = 1;
})();
function foo() {
var a= 1;
}
foo();
就是利用函数会生成函数作用域的特性,自执行函数可以写匿名函数,比较方便,也少一个污染
第二部分
- this是什么时候确定下来的?
this是调用时确定的,根据调用时的综合情况确定下来的 - this的绑定方式有多少种?优先级是?
默认绑定: 非严格模式下是window,严格模式下是undefined
隐式绑定: 大概的说是谁调用指向谁,有时候会有多层引用的情况
const obj0 = {
a: 0,
foo: function () {
console.log(this.a);
}
};
const obj1 = {
a:1,
obj0:obj0
};
const obj2 = {
a:2,
obj1:obj1
};
obj2.obj1.obj0.foo();//0
这个时候就是最近的那层,像上面的例子就是obj0最近的一层调用的,还有一点要注意的就是函数的赋值会导致this的变化或者丢失
const obj0 = {
a:0,
foo:function () {
console.log(this.a);
}
};
const obj1 = {
a:1,
foo:obj0.foo
};
const obj2 = obj0.foo;
obj1.foo();////1 这里和上面有所不同的地方是obj0.foo这个函数直接赋值给obj1.foo和obj2
obj2();// undefined
显式绑定:apply,call,bind,this指向传入的参数
new绑定:this指向new新建的对象
- apply,call,bind区别是?
首先apply和call作用是一样的,传参方式不一样apply(obj,[arg0,arg1,arg2]),call(obj,arg0,arg1,arg2),apply和call和bind的区别就是,apply和call是绑定了立即执行返回且undefined,bind是绑定了不执行返回绑定后的函数 - new在函数里发生了什么?
1,创建一个新的对象
2.把这个对象的proto连接到构造函数的prototype上
3.把this指向这个对象
4.若无renturn就返回这个对象 - 箭头函数this?前面4种方式?
箭头函数的this做过处理,在进入函数前this指向哪里,进入函数后就指向哪里,前面四种绑定this的方式在箭头函数里面是无效的 - null是否是Object类型?
严格上来说null不是object类型,typeof null为object只是js的一个bug,原因是因为js的变量存储为2进制.typeof会根据前面三位是否都为0判断是否是object,而null前三位刚好为0 - 为什么简单基本类型能调用一些方法或者属性?
类似str,num,boolean基本类型本来是没有属性和方法的,但是在调用属性和方法的时候,就是会自动包装成对应的对象,然后引用后会销毁 - 对象的key是什么类型的,不是会怎么样?
对象的key都是字符串类型的,如果穿的不是字符串类型也会转化成字符串类型,之前还想过利用对象key的唯一性去去重,但是key只能是字符串也就是'1',1,true,'true'这种类型就会区分不了了 - 数组下标是什么类型,若不是会怎么样
数组的下标是数字类型的,若传的不是数字类型,但是正整数的字符串形式,会转化成对应的数字 - 深拷贝和浅拷贝有啥区别
浅拷贝基本只是第一层断开联,如果对象里面还有类似对象数组之类的引用类型就会失效,深拷贝是完全的断开联系,无论多少层 - JSON.parse(JSON.stringify())的方式深拷贝对象有啥问题?
这样确实在一定程度上能实现深层的深拷贝,但是会有一些问题,例如如果有函数会消失,new Date对象会变成单纯的字符串之类的问题 - 浅拷贝的方式
可以用for in循环,object.assign,es6里面的{...} - 如何获取属性描述符?有什么属性?有什么用?
用getOwnPropertyDescriptor获取
const obj1 = {a:[1],b:2};
console.log(Object.getOwnPropertyDescriptor(obj1, 'a'));
//configurable: true enumerable: true value: [1] writable: true
有writable,value,enumerable,configurable,还可以设置set和get
value显而易见就是值了,writable就是限制能否修改值也就是value的权限,enumerable就是可枚举,如果设置为false,for in循环是拿不到的,es6的for of循环也一样,但是hasOwnProperty判断还是返回true的,in判断也是返回true的.configurable就是能否配置,为false的时候,就不能修改属性描述符了,而且是不可逆的,并且也不能删掉这个属性
- 如何设置上述的特性
用defineProperty设置
const obj1 = {a:[1],b:2};
Object.defineProperty(obj1,'a',{
value: 2,
writable:false
});
console.log(Object.getOwnPropertyDescriptor(obj1, 'a'));
//configurable: true enumerable: true value: 2 writable: false
- get,set是什么?怎么设置?
const obj1 = {
get a(){
return 2
}
};
Object.defineProperty(obj1,'b',{
get(){
return this.a*2
}
});
console.log(obj1.a); //2
console.log(obj1.b); //4
两种方法设置,get和set最好成对出现,否则会吃出现一些意料之外的问题.这里附上尝试利用get和set实现双向数据绑定链接
- 如何判断属性是不存在还是设置值为undefined
利用hasOwnProperty判断一下就可以了 - 原型对象是什么
新建一个对象的时候会创建一个新的空对象并和新建的对象产生关联,那个就是原型对象 - 原型对象作用是什么
构造函数的原型对象的属性和方法都可以被这个构造函数创建的实例调用 - 原型链是什么
每一个对象都有自己的原型对象,obj.proto会指向他构造函数Obj.prototype,Obj.prototype也是一个对象,所以也有自己的原型对象,所以它指向Object.prototype,最后Object.prototype会指向null,也就是原型链的尽头 - for in循环会检查原型链上面的属性吗?那我只要自身的怎么办?
for in会遍历自身和整条原型链上面enumerable为true的所有属性,如果只想要自身的属性可以用hasOwnProperty判断一下 - 分析myObject.foo = 'bar'的几种情况
1.自身如果有这个属性的,会去判断writable是否为true,如果为true则直接替换,如果不为true则修改失败,严格模式下会报错,普通模式下会忽略
2.自身没有这个属性的,会去原型链上面找,如果找到这个属性的,判断writeable,true则发送屏蔽属性,就是在自身新建一个这个属性,原型链上面那个就拿不到了.如果为false同样会修改失败
3.如果自身和原型链上面都找不到这个属性,则就直接添加到自身上 - 如果writable阻止了我添加属性,但是我又想添加怎么办?
只读只是限制了=的方式修改属性,我们可以用Object.defineProperty
网友评论