第一题
//第一题
var a = {n:1};//创建对象{n:1},赋值给a
var b = a;//b引用a的对象,实际上此时内存只有一个对象。变量a,b同时指向这个对象
a.x = a = {n:2};//此时将这个对象的键值x赋值,赋值内容是运算表达式a={n:2}的运算结果{n:2}
//a={n:2}这个运算表达式又创建了一个对象{n:2},同时让a指向这个对象
//此时内存中有两个对象 a指向于新的对象{n:2},b指向于原对象{n:1,x:{n:2}}
console.log(a.x);// -->undefined
console.log(b.x);// -->{n:2}
//第二题
let obj={
num1:117
}
let res=obj;
obj.child=obj={num2:935};
var x=y=res.child.num2;
console.log(obj.child);
console.log(res.num1);
console.log(y);
以上第一题的另一种解析是:
首先 . 运算符优先级高于= ,所以先给{n:1}对象创建了x属性,对象变成{n:1,x:undefined}(当前a和b都是指向此内存对象),然后连等从右往左执行,先把a指向改成{n:2},然后把最初的内存对象的x属性指向改成{n:2}(因为.运算符已执行,所以此时a.x是指{n:1,x:undefined}的x属性),内存对象变成{n:1,x:{n:2}}。此时只有b还是指向这个内存对象 所以:
a.x -->undefined
b -->{n:1,x:{n:2}}
第二题
const obj={
flag:true,
}
function a() {
this.flag=false;
return obj;
}
const A=new a();
console.log(A.flag);
第三题
var num= 10
let obj={num:20}
obj.fn =(function(num){
this.num= num *3;
num++
return function(n){
this.num += n
num++
console.log(num)
}
})(obj.num)
let fn= obj.fn
fn(5)
obj.fn(10)
console.log(num, obj.num)
第四题
var a={},
b={key:'b'},
c={key:'c'};
a[b]=123;
a[c]=456;
console.log(a[b]);
// 对象有两种方法设置和引用属性,obj.name和obj['name'],方括号里可以字符串、数字和变量设置是表达式等,但是最终计算出来得是一个字符串,
// 对于上面的b和c,它们两个都是对象,所以会调用toString()方法转成字符串,对象转成字符串和数组不一样,和内容无关,结果都是[object Obejct],所yi
// a[b]=a[c]=a['[object Object]']。
第五题
function fruits() { }
fruits.prototype = {
color: 'red',
say: function () {
console.log(this.color);
}
};
var apple = new fruits();
apple.say();
banana = { color: 'yellow' };
apple.say.call(banana);
apple.say.apply(banana);
apple.say.apply(null);
第六题
const promise = new Promise((resolve, reject) => {
console.log(1);
setTimeout(() => {
console.log("begin");
resolve("suss");
console.log("end");
}, 0);
console.log(2);
});
promise.then((data) => { console.log(data); });
console.log(4);
第七题
console.log(!![]);
console.log(!!'');
变量释放问题
//第一题
var a ="hello";//全局变量
window.b ="word";//全局变量
delete a;
delete b;
console.log(typeof a);//结果:string
console.log(typeof b);//结果:undefined!
!function b(){
var c = 1;//局部变量
d = 2;//全局变量
delete c;
delete d;
console.log(typeof c);//结果:number
console.log(typeof d);//结果:undefined
}()
//第二题
function A(x){
this.x=x;
}
A.prototype.x=1;
function B(x){
this.x=x;
}
B.prototype=new A();
var a=new A(2),b=new B(3);
delete b.x;
console.log(a.x);//2
console.log(b.x);//underfined
//第二题
let a=1;
let obj={
x:1
}
delete a;
delete obj.x;
delete 2;
console.log(a);
console.log(obj.x);
console.log(2);
结论:
- 使用var、let创建的变量不能使用delete释放内存
- 不使用var、let创建的变量可以使用delete释放内存
第八题
function Foo() {
Foo.a = function () {
console.log(1)
}
this.a = function () { console.log(2) }
}
Foo.prototype.a = function () { console.log(3) }
Foo.a = function () { console.log(4) }
Foo.a();
let obj = new Foo();
obj.a();
Foo.a();
- Foo.a() 这个是调用 Foo 函数的静态方法 a,虽然 Foo 中有优先级更高的属性方法 a,但 Foo 此时没有被调用,所以此时输出 Foo 的静态方法 a 的结果:4
- let obj = new Foo(); 使用了 new 方法调用了函数,返回了函数实例对象,此时 Foo 函数内部的属性方法初始化,原型链建立。
- obj.a() ; 调用 obj 实例上的方法 a,该实例上目前有两个 a 方法:一个是内部属性方法,另一个是原型上的方法。当这两者都存在时,首先查找 ownProperty ,如果没有才去原型链上找,所以调用实例上的 a 输出:2
- Foo.a() ; 根据第2步可知 Foo 函数内部的属性方法已初始化,覆盖了同名的静态方法,所以输出:1
第九题
function fun() {
return () => {
return () => {
return () => {
console.log(this.name)
}
}
}
}
var f = fun.call({ name: 'foo' })
var t1 = f.call({ name: 'bar' })()()
var t2 = f().call({ name: 'baz' })()
var t3 = f()().call({ name: 'qux' })
箭头函数没有自己的this也并不能使用call,apply以及bind去绑定this,会选择去继承父级作用域的this,所以后面几次的call实际上是失败的,所以箭头函数层层向上寻找name,只会在最外层的fun函数作用域中找到this指向{name: ‘foo’}对象的name属性。假设此处将fun函数改成箭头函数的声明方式,那么返回的值将会是undefined.
第十题
//第一例
var a=1
function fun(){
var a=2
console.log(a);//2
}
fun()
//第二例
var b=1;
for(var c=0;c<1;c++){
var b=2;
}
console.log(b)//2
使用var声明的变量存在很大的问题。在本题中fun函数内部的作用域为局部作用域,log打印会优先找到局部作用域的a变量,所以打印为2.
而在第二例中,由于for循环内部对于使用var声明的变量不是一个局部作用域,所以for循环内部的变量声明会和外部的变量声明一起发生变量提升,所以b=2会覆盖前一个b=1,打印出2,这种情况同样适用于if判断。
第十一题
//第一例
async function async1() {
console.log(1);
const result = await async2();
console.log(3);
}
async function async2() {
console.log(2);
}
Promise.resolve().then(() => {
console.log(4);
});
setTimeout(() => {
console.log(5);
});
async1();
console.log(6);
//第二例
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('同步1');
setTimeout(() => {
console.log('setTimeout');
}, 0)
async1();
new Promise((resolve) => {
console.log('promise1');
resolve();
}).then(() => {
console.log('promise2');
});
console.log('同步2');
//第三例
Promise.resolve()
.then(() => {
console.log(0);
return Promise.resolve(4);
})
.then((res) => {
console.log(res);
});
Promise.resolve()
.then(() => {
console.log(1);
})
.then(() => {
console.log(2);
})
.then(() => {
console.log(3);
})
.then(() => {
console.log(5);
})
.then(() => {
console.log(6);
});