面试题,哈哈哈哈!

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__""!!!
*/

原型链与 new的过程

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
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring的底层原理主要包括以下几个方面:IOC(Inverse of Control,控制反转)、AOP(Aspect-Oriented Programming,面向切面编程)、Bean生命周期管理、以及Spring的核心组件。 1. IOC(控制反转):IOC是Spring的核心思想,它通过容器管理和维护对象之间的依赖关系,将对象的创建、组装和生命周期交给容器来管理。在Spring中,我们通过配置文件或者注解来描述对象之间的依赖关系,而不是在代码中直接去创建和关联对象。 2. AOP(面向切面编程):AOP是一种编程思想,它将应用程序的业务逻辑与横切关注点(如日志、事务、安全等)分离开来,实现了模块化的设计。Spring利用AOP可以实现诸如日志记录、性能统计、事务管理等横切关注点的功能。 3. Bean生命周期管理:Spring通过Bean生命周期管理来管理Bean的创建、初始化、使用和销毁等过程。在容器启动时,Spring会根据配置信息创建Bean实例并进行初始化,然后在需要使用时将Bean注入到其他对象中。当容器关闭时,Spring会销毁这些Bean实例。 4. Spring的核心组件:Spring的核心组件包括容器(ApplicationContext)、BeanFactory、BeanPostProcessor等。容器负责管理和维护Bean的生命周期,提供依赖注入和AOP的支持;BeanFactory是Spring的核心接口,定义了容器的基本功能;BeanPostProcessor是一个回调接口,可以在Bean实例化、初始化和销毁的过程中介入进行扩展。 总之,Spring底层原理主要围绕IOC、AOP和Bean生命周期管理展开,通过这些机制实现了松耦合、可维护和可扩展的应用程序开发。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值