Q1
function getPersonInfo(one, two, three) {
console.log(one);
console.log(two);
console.log(three);
}
const person = "Lydia";
const age = 21;
getPersonInfo`${person} is ${age} years old`;
//['','is','years old'],Lydia,21
//如果使用标记的模板字符串,则第一个参数的值始终是字符串值的数组。 其余参数获取传递到模板字符串中的表达式的值!
Q2
function checkAge(data) {
if (data === { age: 18 }) {
console.log("You are an adult!");
} else if (data == { age: 18 }) {
console.log("You are still an adult.");
} else {
console.log(`Hmm.. You don't have an age I guess`);
}
}
checkAge({ age: 18 });
在比较相等性,原始类型(string,number,boolean,null,undefined)通过它们的值进行比较,而对象通过它们的引用进行比较。JavaScript检查对象是否具有对内存中相同位置的引用。
我们作为参数传递的对象和我们用于检查相等性的对象在内存中位于不同位置,所以它们的引用是不同的。
这就是为什么{ age: 18 } === { age: 18 } 和 { age: 18 } == { age: 18 } 返回 false的原因。
Q3
const obj = { 1: "a", 2: "b", 3: "c" };
const set = new Set([1, 2, 3, 4, 5]);
obj.hasOwnProperty("1");
obj.hasOwnProperty(1);
set.has("1");
set.has(1)
所有对象键除了(symbol,Set)都会被存储为字符串,即使没有给定字符串类型的键, 这就是为什么obj.hasOwnProperty(‘1’)返回true。new Set中没有"1",set.has(‘1’)返回false。 它有数字类型1,set.has(1)返回true。
Q4
const a = {};
const b = { key: "b" };
const c = { key: "c" };
a[b] = 123;
a[c] = 456;
console.log(a[b]);//456
对象键自动转换为字符串。
我们试图将一个对象设置为对象a的键,其值为123。但是,当对象自动转换为字符串化时,它变成了[Object object]。
所以我们在这里说的是a[“Object object”] = 123。
然后,我们可以尝试再次做同样的事情。 c对象同样会发生隐式类型转换。那么,a[“Object object”] = 456。
然后,我们打印a[b],它实际上是a[“Object object”]。 我们将其设置为456,因此返回456。
Q5
const numbers = [1, 2, 3];
numbers[10] = 11;
console.log(numbers);//[1, 2, 3, empty × 7, 11]
console.log(numbers[5]);//undefined
当你为数组中的元素设置一个超过数组长度的值时,JavaScript会创建一个名为“空插槽”的东西。 这些位置的值实际上是undefined。
Q6
//Q1
(() => {
let x, y;
try {
throw new Error();
} catch (x) {
(x = 1), (y = 2);
console.log(x);//这的x是catch块级作用域的,当前x = 1,y = 2;作用域外 x 为undefined
}
console.log(x);
console.log(y);
})();
//Q2
(() => {
let x, y;
try {
throw new Error();
} catch ({x,y}) {
(x = 1), (y = 2);
console.log(x);//这的x是catch块级作用域的,x = 1,y = 2;作用域外 x,y 为undefined
}
console.log(x);
console.log(y);
})();
catch块接收参数x。当我们传递参数时,这与变量的x不同。这个变量x是属于catch作用域的。
之后,我们将这个块级作用域的变量设置为1,并设置变量y的值。 现在,我们打印块级作用域的变量x,它等于1。
在catch块之外,x仍然是undefined,而y是2。 当我们想在catch块之外的console.log(x)时,它返回undefined,而y返回2。
Q7
function Person(){
this.age = 20;
console.log(this.age);
}
Person.money = 2000;
Person.prototype.say = function(){
console.log('my age is 30!!');
}
Person.say();
/*
TypeError: Person.say is not a function
Person.prototype !== Function.prototype
构造函数Person.prototype和function Person(){}本身没有属于被属于关系,
只是function Person(){}有一个属性prototype指向Person.prototype;
prototype在原型链中只是起一个辅助作用,换句话说,他只是在new的时候有着一定的价值,真正贯穿整个原型链的是""__proto__""!!!
*/
Q8
//new 实现原理
function newFun(ConstructorFun){
let obj = {};
//1、创建一个空对象
obj.__proto__ = ConstructorFun.prototype;
//2、新对象的__proto__指向构造函数的原型,执行原型连接
let result = ConstructorFun.apply(obj,args);
//3、构造函数的this指向新的对象,或者说执行构造函数,将属性方法添加到创建的空对象上
if( result && (typeof (result) === object' || typeof (result) === 'function') ){
return result;
//4、如果执行构造函数后,返回的是一个对象result,那么直接返回这个对象result
否则返回创建的对象obj
}
return obj;
}
Q9
JS是弱类型导致隐式转换频繁,但有规则:
js在进行加法运算的时候, 会先推测两个操作数是不是number。
如果是,则直接相加得出结果。
如果其中有一个操作数为string,则将另一个操作数隐式的转换为string,然后进行字符串拼接得出结果。
如果操作数为对象或者是数组这种复杂的数据类型,那么就将两个操作数都转换为字符串,进行拼接
如果操作数是像boolean、null、undefined这种的简单数据类型,那么就将操作数转换为number相加得出结果。
//特例
Number(null); //0
Number([]); //0
null+null //0
undefined+undefined //NaN
undefined+null //NaN
[]+{} //'[object Object]'
[].toString() //''
[1,"a"].toString() //"1,'a'"
{}.toString() //"[object Object]"
({a:1}).toString() //"[object Object]"
'2' + function (){} // "2function (){}"
{}+[] // 0 因为js解释器会将开头的 {} 看作一个代码块,而不是一个js对象,于是真正参与运算的是+[],就是将[]转换为number
Boolean(undefined、null、-0或0或+0、NaN、''(空字符串)) //false 其他全部为true
2 <= 3 <= 4 // 等价于 ([( 2 <= 3 )=> (true == 1) ]<= 4 ) => true 原因就是 0 == false,1 == true有boolean值则转成Number
2 <= 1 <= 4 //等价于 2 <= 1 => (false == 0) <= 4 => true