3.27大二下第一次分享会总结

68 阅读3分钟

一、服务端渲染(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不会变量的声明提升,但是也会有一个“暂时性死区提升”,告诉执行环境,我内部有声明,但是是在声明之前调用的,出现暂时性死区,不会沿作用域链向外查找。

eca634cef32d2385addfc53b330a0d7d.png

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