JavaScript-Basic Day2-5 Notes

1、如何理解 == 和 === 潜在区别?

console.log(3 == '3')
console.log(3 === '3')

在 JavaScript 中,===== 是两种不同的比较操作符,它们在比较两个值时的行为有所不同:

  1. 双等号(==) - 抽象相等运算符

    • 这个运算符在比较两个值时会进行类型转换。如果两个值的类型不同,JavaScript 会尝试将它们转换为相同的类型,然后再进行比较。
    • 在你的例子中:console.log(3 == '3'),数字 3 和字符串 '3' 类型不同,但 JavaScript 会将字符串 '3' 转换为数字 3,然后比较这两个数字。由于转换后的值相同,所以这个表达式的结果是 true
  2. 三等号(===) - 严格相等运算符

    • 这个运算符在比较两个值时不会进行类型转换。它要求两个值的类型和值都必须相同,才会返回 true
    • 在你的例子中:console.log(3 === '3'),尽管数字 3 和字符串 '3' 的内容相同,但它们的类型不同(一个是数字类型,另一个是字符串类型),因此这个表达式的结果是 false

总结

  • 使用 == 时,如果值的类型不同,JavaScript 会进行类型转换后再比较。
  • 使用 === 时,如果值的类型不同,比较结果直接为 false,不会进行类型转换。

在编写 JavaScript 代码时,推荐使用 === 来避免因隐式类型转换导致的意外结果,这样可以使得代码的逻辑更加清晰和可预测。

 

2、为什么如下两行代码会分别返回3,4

let arr = ['pink', 'hotpink']
console.log(arr.push('yellow'))   //3
console.log(arr.push('blue'))     //4

在 JavaScript 中,Array.prototype.push() 方法用于将一个或多个元素添加到数组的末尾,并返回数组新的长度。

 

3、如何理解这个unshift() 这个单词为什么和向前插入能够建立联系呢?

unshift 这个单词由两部分组成:"un-" 和 "shift"。

  1. "shift" 在英语中意味着移动或转移。在编程语境下,"shift" 通常用来描述从数据结构(如数组)的一端移除元素的操作。例如,JavaScript 中的 shift() 方法就是从数组的开头移除第一个元素。

  2. "un-" 是一个前缀,表示相反或反向的动作。

结合这两部分,unshift 字面上可以理解为“做 shift 的相反动作”,即不是从一端移除元素,而是向相反的方向,也就是数据结构的开头添加元素。

在 JavaScript 中,Array.prototype.unshift() 方法正是这样的操作:它允许你向数组的开头添加一个或多个元素。当使用 unshift 方法时,任何新添加的元素都会被插入到数组已有元素的前面,而原有元素则向后移动。

let arr = ['pink', 'hotpink'];
arr.unshift('red');
console.log(arr);
  • 初始时,arr 是 ['pink', 'hotpink']
  • arr.unshift('red') 将 'red' 插入到数组的开头。
  • 执行后,arr 变为 ['red', 'pink', 'hotpink']

unshift 方法不仅在数组开头添加了元素,还返回了新数组的长度。在这个例子中,数组的长度从 2 增加到了 3

 

4、请逐行解释下如下CSS代码

        * {
            margin: 0;
            padding: 0;
        }

        .box {
            display: flex;
            width: 700px;
            height: 300px;
            border-left: 1px solid pink;
            border-bottom: 1px solid pink;
            margin: 50px auto;
            justify-content: space-around;
            align-items: flex-end;
            text-align: center;
        }

        .box > div {
            display: flex;
            width: 50px;
            background-color: pink;
            flex-direction: column;
            justify-content: space-between;
        }

        .box div span {
            margin-top: -20px;
        }

        .box div h4 {
            margin-bottom: -35px;
            width: 70px;
            margin-left: -10px;
        }

这段 CSS 代码包含了几个选择器和对应的样式规则,下面是逐行的解释:

  1. * 这是一个通配符选择器,它匹配页面上的所有元素。

* {
    margin: 0;
    padding: 0;
}
  • margin: 0; 将所有元素的外边距设置为 0。
  • padding: 0; 将所有元素的内边距设置为 0。
  • 这通常用于重置浏览器的默认样式,以确保页面元素的样式从头开始设置,避免不同浏览器之间的样式差异。

    2.box 这是一个类选择器,匹配所有具有 class="box" 的元素。

.box {
    display: flex;
    width: 700px;
    height: 300px;
    border-left: 1px solid pink;
    border-bottom: 1px solid pink;
    margin: 50px auto;
    justify-content: space-around;
    align-items: flex-end;
    text-align: center;
}
  • display: flex; 将元素的显示类型设置为 flex,启用 Flexbox 布局。
  • width: 700px; 设置元素的宽度为 700 像素。
  • height: 300px; 设置元素的高度为 300 像素。
  • border-left: 1px solid pink; 设置元素左边框为 1 像素宽、实线、粉色。
  • border-bottom: 1px solid pink; 设置元素底边框为 1 像素宽、实线、粉色。
  • margin: 50px auto; 设置元素的外边距,上下方为 50 像素,左右自动(常用于水平居中元素)。
  • justify-content: space-around; 在 Flex 容器中,所有项目(子元素)沿着主轴(默认是水平方向)均匀分布,项目间的空间比项目与容器边缘的空间大一倍。
  • align-items: flex-end; 所有子元素在交叉轴(垂直方向)的末端对齐。
  • text-align: center; 文本内容在元素内水平居中显示。

  3..box > div 这是一个子选择器,匹配所有 .box 元素的直接子 div 元素。

.box > div {
    display: flex;
    width: 50px;
    background-color: pink;
    flex-direction: column;
    justify-content: space-between;
}

  4..box div span 这是一个后代选择器,匹配所有 .box 元素后代中的 span 元素。

.box div span {
    margin-top: -20px;
}
  • margin-top: -20px; 设置 span 元素的上外边距为 -20 像素,这通常用于调整元素的位置,使其向上移动。

  5 .box div h4 这是一个后代选择器,匹配所有 .box 元素后代中的 h4 元素。

.box div h4 {
    margin-bottom: -35px;
    width: 70px;
    margin-left: -10px;
}
  • margin-bottom: -35px; 设置 h4 元素的下外边距为 -35 像素,这通常用于调整元素的位置,使其向下移动。
  • width: 70px; 设置 h4 元素的宽度为 70 像素。
  • margin-left: -10px; 设置 h4 元素的左外边距为 -10 像素,这通常用于调整元素的水平位置,使其向左移动。

 

5、记住justify-content: space-around 和 space-between之间的区别

space-between会区间两头两尾顶齐。

 justify-content: space-around 则会在两头两位之间流出一段距离。

 

6、解释下如下函数的寻值num的顺序,这是不是有些闭包的含义在里面?和python的闭包有何异同?

    <script>

        let num = 10 
        function fn(){
            let num = 20  // 如果注释这行,会打印出10
            function func(){
                let num = 30 // 如果注释这行,会打印出20。 如果都不注释,按作用域就近取值,会打印出30
                console.log(num)
            }
            func()
        }

        fn()
        

    </script>

这段 JavaScript 代码展示了作用域链和闭包的概念。首先,让我们逐步解释函数的执行和 num 的查找顺序:

  1. 你声明了一个全局变量 num 并赋值为 10

  2. 你定义了一个函数 fn,在 fn 函数内部:

    • 又声明了一个局部变量 num 并赋值为 20
    • 定义了一个嵌套函数 func,在 func 函数内部:
      • 再次声明了一个局部变量 num 并赋值为 30
      • 使用 console.log(num) 打印 num 的值。
  3. 当你调用 fn() 时,fn 函数执行:

    • 首先创建了 fn 的作用域,其中包含变量 num(值为 20)。
    • 接着 fn 调用了内部的 func 函数,创建了 func 的作用域,其中包含变量 num(值为 30)。
    • func 执行时,console.log(num) 打印的是 func 作用域内的 num,因此输出结果是 30

闭包的概念

闭包是指函数可以记住并访问其创建时的作用域,即使该函数在其原始作用域之外被执行。

在这个例子中,func 函数在其创建时的作用域(fn 函数的作用域)之外被调用,但它仍然可以访问 fn 函数作用域内的变量。

JavaScript 闭包与 Python 闭包的异同

  • 相同点:

    • 两者都允许函数访问创建时的作用域中的变量,即使函数在其原始作用域之外被调用。
    • 两者都可以用于创建具有私有变量的函数。
  • 不同点:

    • 语法:JavaScript 和 Python 的语法不同,这影响了闭包的写法。
    • 作用域规则:Python 有明确的块作用域概念,而 JavaScript 有函数作用域和词法作用域。
    • 类型系统:Python 是动态类型语言,而 JavaScript 也是动态类型语言,但它们的类型系统和类型推断机制可能有所不同。
    • 执行环境:Python 通常用于科学计算、数据分析等领域,而 JavaScript 主要用于网页开发,执行环境主要是浏览器或 Node.js。

在你提供的代码示例中,闭包的使用允许 func 函数记住并访问它被创建时的变量 num(值为 30),即使它在 fn 函数被调用后才执行。

这种特性在 JavaScript 中非常有用,尤其是在处理异步操作、封装私有变量和方法等场景。

 

7、关于匿名函数、具名函数如下细节需要注意。

        fn(1, 2) // 匿名函数没有函数提升, 无法先调用,后定义。 这样执行必然报错
        let fn = function (x, y){   //事实上,只要加了let, 必须先声明后使用
            console.log(x + y)
        }
    
        funcAdd(1, 5) // 具名函数有函数提升,可以这样成功执行。[具名函数调用可以写在任何位置]
        function funcAdd(x, y){
            console.log(x + y)
        }       

总结:

  1. 具名函数的调用可以写到任何位置;

  2. 函数表达式,必须先声明函数表达式,后调用。

 

8、关于立即执行函数的理解,和使用

作用:

  1、立即执行函数可以防止变量污染,即便好几个同名变量,因为都是局部变量,所以不会互相干扰;

  2、立即执行函数不需要额外调用,语法中已经就包括调用了;

两种语法:(1).  (function(形参){})(实参)  (2). (function(形参){}(实参))   其实分辨就是看后面调用的括号是写在里面,还是写在外面。

对外表现为,是一个括号,还是两个括号。

注意:多个立即执行函数之间,需要用封号隔开;

例如如下代码的多个变量,虽然重名,但也不会产生触痛

    (function (x, y){
        console.log(x + y)
    })(1, 2);
    (function (x, y){
        console.log(x + y)
    })(3, 4);

    (function(){
        let num1 = 10
        let num2 = 20
        console.log(num1 + num2)
    }());
    (function(){
        let num1 = 10
        let num2 = 20
        console.log(num1 + num2)
    }());

 

9、Boolean转化如下几个特殊值的时候,需要注意下

console.log(Boolean(undefined))   //false
console.log(Boolean(null))    //false
console.log(Boolean(NaN))   //false

 

10、 JavaScript的如下循环和python还不太一样,注意区分下。

    let arr = ['pink', 'red', 'blue']
    // for(let k in arr){
    //     // console.log(k) // 这样返回的是索引0,1,2。和python不一样
    //     // console.log(arr[k])
    //     console.log(arr[k])
    // }

    let obj = {
        uname: 'bruce老师',
        age: 18,
        gender: '男'
    }

    for(let k in obj){
        // console.log(k) // 这样返回的是uname, age, gender。和python不一样
        // console.log(obj.uname)
        // console.log(obj.k)
        // console.log(obj.'uname')
        // console.log(obj['uname'])
        console.log(obj[k])
    }

 

 

11、关于变量和对象的共享内存问题,如下的例子可以体会下。

    <script>
        let num1 = 10
        let num2 = num1 
        num2 = 20
        console.log(num1) // 10, 变量并不会共享同一块内存


        let obj1 = {
            age: 18
        }

        let obj2 = obj1 
        obj2.age = 20
        console.log(obj1.age)  // 20, 但是这里的object会共享同一块内存
    </script>

 

 

 

 

 

 

 

 

 

 

posted @ 2024-08-18 19:02  AlphaGeek  阅读(14)  评论(0)    收藏  举报