一、服务端渲染(SSR)和客户端渲染(CSR)各自优缺点的总结
二、函数的参数的形参、作用域相关知识
1.引用传参实质——拷贝指针(把对象作为参数传递时,传递的是对象的地址)
解释:即如下函数内部的变量(比如 obj)和外部的对象(比如 person)都指向同一个对象。但它们都指向相同的内存位置, 修改对象的属性会影响外部对象,因为传递的是同一个地址。
- 修改对象的引用不会影响外部对象,因为你只是让函数内的
obj指向了一个新的对象,而不是修改原始对象本身,此处就涉及到了指针的拷贝(拷贝指针),本质上是把指向这个地址的指针拷贝了一份,若修改对象的属性,则还是同一个地址,影响外部对象,若直接修改对象的引用,那么直接改变了这个内部对象的引用(地址),不会影响外部,因为仅为拷贝而已
function modifyObject(obj) {
obj.name = 'Alice'; // 修改了对象的属性
obj = { name: 'Bob' }; // 这里是重新赋值了引用,指向了一个新对象
console.log(obj.name)
}
let person = { name: 'John' };
modifyObject(person);
console.log(person.name); // 输出: Bob Alice
2.关于arguments在函数内部操作参数的知识
arguments是一个类数组,只有length属性记录长度,不可调用其他数组方法,更方便的方法是function(...args){ console.log(args) /此时args即是一个真数组
1.按照形参的顺序输出,
(
function foo() {
console.log(arguments[0]);
console.log(arguments[1]);
}
foo(10, 20); //10 20
2、若形参中没有传入参数,如例子中第二个参数,那么会无法通过后续赋值添加,此处b 在没有传参的情况下默认是 undefined,后续修改的arguments[1],只是为arguments[1]赋值,并未修改b的值
function foo(a,b) {
arguments[1] = 2;
console.log(b);
}
foo(1); //undefined
传参时由此参数,即可修改
function foo(a,b) {
arguments[1] = 2;
console.log(b);
}
foo(1, 1) // 2
3.箭头函数报错,因为无法找到作用链上arguments的声明和值
let foo = () => {
console.log(arguments[0]);
}
foo();
3.引申出的形参作用域问题
let b = 2;
function foo(b = 3 , a = b) {
console.log(a);
}
foo(); //3
实际上形参作用域 就是位于函数内部作用域的顶部,上面代码等同于
let b = 2;
function foo() {
let b = 3
let a = b
console.log(a);
}
foo(); //3
注意是let用块级作用域,符合es6新规范,例如如下
let b = 2;
function foo(a = b , b = 3) {
return a;
}
foo(); // 报错
等同于
let b = 2;
function foo() {
let a = b
let b = 3
return a;
}
foo(); // 报错
此时a被复制为b,但是b未被声明,所以出现暂时性死区,有可能会好奇,函数内部找不到b的声明不会沿作用域链向外查找吗? 不会的,因为虽然let不会变量的声明提升,但是也会有一个“暂时性死区提升”,告诉执行环境,我内部有声明,但是是在声明之前调用的,出现暂时性死区,不会沿作用域链向外查找。
4.js是如何调用简单数据类型的方法
思考:引用数据类型,如Array的方法,是写在Array.prototype上的,供实例对象使用,如splice、push等 但是简单数据类型呢?其实也是用了一步转化,调用一个构造函数创建一个简单数据类型的包装对象,用这个包装对象(实例)调用构造函数Number的原型对象上共享的实例方法生成要的转化结果,然后删除这个中间桥梁包装对象,输出转化结果即可
let a =2
let obj = new Number(a)
let b = obj.toString()
delete ob
console.log(typeof(b)) //输出string
//等效于 let b = a.toString()
如下例子,输出undefined原因即为,属性 tempProp 被添加到了临时对象上(上面代码中的obj),但包装对象在代码执行后被销毁
let num = 2;
num.tempProp = "test"; // 试图在数字上添加属性
console.log(num.tempProp); // undefined