前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript高级语法补充(函数参数传递、in delete关键字、比较运算符隐式转换)

JavaScript高级语法补充(函数参数传递、in delete关键字、比较运算符隐式转换)

原创
作者头像
帅的一麻皮
修改2020-05-18 18:15:34
6250
修改2020-05-18 18:15:34
举报
文章被收录于专栏:前端与Java学习前端与Java学习

01-js高级语法补充

1.1-值类型与引用类型复习

1.值类型 (5种):  栈中存储的是数据,赋值时拷贝的也是数据。修改拷贝后的数据对原数据没有影响。

2.引用类型(2种) : 栈中存储的是地址,数据在堆中,赋值时拷贝的也是地址。修改拷贝后的数据对原数据有影响的。

代码语言:javascript
复制
<script>
        //1.值类型
        var num1 = 10;
        var num2 = num1;
        num2 = 20;
        console.log(num2);//20
        console.log(num1);//10

        //2.引用类型
        var arr1 = [10,20,30];
        arr2 = arr1;
        arr2[0] = 100;
        console.log(arr2);//[100,20,30]
        console.log(arr1);//[100,20,30]
</script>

==1.2-参数传递==

ECMAScript中所有的函数的参数都是按值传递的,也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。基本类型值的传递如同基本基本类型变量的复制一样,而引用类型值的传递,如同引用类型变量的复制一样。有不少开发人员会在这一点上感到困惑,因为访问变量有按值和按引用两种方式,而参数只能按值传递。

在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(arguments对象中的一个元素),在向参数传递引用数据类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部 --《JavaScript高级程序设计》以上都是书中原话

在读到《JavaScript高级程序设计》的4.1.3参数传递这一章的时候十分困惑,书中例举了几个案例来说明传递参数都是按值传递的

代码语言:javascript
复制
function addTen(num){
    num+=10;
    return num;
}
var count = 20;
var result = addTen(count);
console.log(count)//20 没有变化
console.log(result)//30

以上这个案例传递的是基本数据类型很好理解,num传递的是值不会影响函数外部变量count,他们仅仅具有相同的值。

但是我们接着使用对象,那就不那么好理解了:

代码语言:javascript
复制
function setName(obj){
    obj.name = "Nicholas";
}
var person = new Object();
setName(person);
console.log(person.name);//“Nicholas”

以上代码创建了一个对象保存在了变量person中,然后将对象传入setName()函数中之后就被复制给了obj,在这个函数内部,obj和person引用的是同一个对象,换句话说,即使这个变量是按值传递的,obj也会按照引用来访问同一个对象。于是当在函数内部修改了obj的name属性后,函数外部的person也将有所反映;到这里很多人会认为在局部作用域中修改的对象会在全局作用域中反应出来,说明参数是按引用传递的,至此书中又举了一个经过修改后的例子:

代码语言:javascript
复制
function setName(obj){
    obj.name = "Nicholas";
    obj = new Object();
    obj.name = "Greg";
}
var person = new Object();
setName(person);
console.log(person.name);//“Nicholas”

这个例子在吧person传递给setName()后其name属性被设置为Nicholas然后又将一个新对象赋值给了obj,同时将其name改为了“Greg”,如果person是按引用传递的,那么person就会自动被修改为指向其name属性值为“Greg”的新对象,但是接下来访问的时候person.name依旧是"Nicholas"。这说明即使在函数内部修改了参数的值,但原始的引用仍然保持不变。实际上,当函数内部重写obj时,这个变量引用的就是一个局部对象了,而这个局部对象会在函数执行完毕后立即被销毁。


以上就是《JavaScript高级程序设计》对函数传递参数的说明,但是还是很难理解向参数传递引用类型的值时是按值传递的的。这里我的理解是函数的参数都是按值传递的,传Object类型也是一样,只不过这个值是地址值,也就是说函数的参数传递的都是栈空间中的值(值类型的值就是数据,引用类型的值就是地址)上面的代码我是这么理解的:

我们把person的地址值传递给obj后,obj和person都指向了堆内存中的同一块地址(假设是a地址),所以这里对obj进行添加或者删除属性的操作,都是在a地址上操作的,所以相应的变化会反映在person对象上。

那么,当对obj重新赋值(新的地址b),这个时候就切断了obj和a地址之间的联系,所以对obj上的任何操作也不会反映到person对象上。如果函数的参数是按引用传递的话,person也会指向地址b,然而事实上person指向的是地址a

所以:引用类型传递,传递的是地址的值,修改成员对象会影响原对象,但对变量重新赋值,不会影响原对象

1.3-in关键字三个作用

代码语言:javascript
复制
<script>
        //1.for-in循环遍历对象属性
        var person = {
            name: '张三',
            age: 38
        };

        for (var key in person) {
            console.log(key);//获取对象属性名字符串
            console.log(person[key]);
        };

        //2.判断对象是否 包含 某个属性
        var student = {
            name: '班长',
            age: 38,
            sex: '男'
        };

        console.log("name" in student)//true
        console.log("age" in student)//true
        console.log("sex" in student)//true
        console.log("girlFriend" in student)//false

        //3.判断数组是否 包含 某个下标
        var arr = [10, 20, 30, 40, 50];
        console.log(5 in arr);//false
        console.log(4 in arr);//true
        console.log(0 in arr);//true

        //如何判断数组中是否包含某个元素
        console.log(arr.indexOf(10));//0    如果有则返回该元素下标
        console.log(arr.indexOf(100));//-1  如果没有则返回固定值  -1    
</script>

1.4-delete关键字两个作用

代码语言:javascript
复制
<script>
        //delete关键字两个作用

        //1.删除对象的属性 : delete 对象名.属性名

        /*对象的属性既可以动态添加,也可以动态删除*/
        var person = {
            name: '班长',
            sex: '男'
        }
        person.girlFriend = '苍老师';//动态添加属性
        delete person.sex;//动态删除属性
        console.log(person);

        //2.删除没有使用var声明的变量   ( 有var声明的delete删除无效 )

        num = 10;
        delete num;
    // console.log ( num );//程序报错num is not defined
</script>

1.5-比较运算符隐式转换

1.复习隐式转换 : 运算符在运算的时候,如果两边的数据类型不一致,则会自动转成一致后运算。

  • a. 其他类型转string :  + 连接符
  •             b. 其他类型转number :  
    •                 自增自减(++ --)
    •                 算术运算符( + - * / %)
    •                 关系运算符 :  > >= < <= == != === !==
  •             c. 其他类型转boolean :  ! 逻辑非

2. 特殊情况

  •             === : 全等运算符。 不存在类型转换, 先比较类型,然后比较值
  •             ==  :  比较运算符。 隐式转换规则是转成number,但是有前提条件

3. x == y: 比较运算符分为五种情况

  •             3.1 x和y 都为 null或undefined
    •                 * 不会类型转换,得到固定值true
  •             3.2 x或y 为NaN 
    •                 * 不会类型转换,得到固定值false  (NaN与任何数据都不等,包含自身)
  •             3.3 x和y 都为 string,boolean,number ,且类型不一致
    •                 * 会类型转换, 会把其他类型转成number后计算
  •             3.4 x或y 为引用类型 (一个是引用类型,一个是值类型)
    •                 * 前提 : 引用类型会先调用valueOf(),然后调用toString(),再来计算  (最终变成字符串来比较)
      •                     * valueOf() : 一般引用类型,返回自身(一般忽略)
      •                     * toString() : 数组是join()字符串, 对象是固定字符串 '[object Object]'
  •             3.5 x和y 都为引用类型。 则会比较两者地址,地址一样则为true,否则为false

1. === : 全等运算符(不存在类型转换)

代码语言:javascript
复制
        // 严格匹配 : 数据类型 与 值 必须要同时相等
        console.log('1' === 1 );//false
        console.log( 1 === 1 );//true
        console.log( undefined === null );//false

2. == : 比较运算符 : 隐式转换是有前提条件的  ( x == y )

2.1 x和y  都为 null或者undefined

代码语言:javascript
复制
        // 不会类型转换,固定返回true
        console.log( Number(null) );//0
        console.log( Number(undefined) );//NaN
        console.log( null == null );//true
        console.log( undefined == undefined );//true
        console.log( null == undefined );//true   

2.2 x或y  为NaN 

代码语言:javascript
复制
        // 不会类型转换,固定返回false (NaN与任何数据都不等)
        console.log( NaN == 0 );//false
        console.log( NaN == undefined );//false
        console.log( NaN == null );//false
        console.log( NaN == NaN );//false

2.3 当x或y 都为 :string,number,boolean。 且数据类型不一致,此时会转换成number后运算

代码语言:javascript
复制
console.log( 1 == '1' );//true   1 == Number('1')
console.log( false == '0' );//true   Number(false) == Number('0')  0 == 0        

2.4 x或y 存在引用类型,则会转成 `原始值` 后比较

代码语言:javascript
复制
        //  一个是引用类型,一个是基本类型
        // 引用类型转原始值 : 先调用对象的valueOf() 方法获取原始值,然后调用toString() 转成字符串比较
        // a :  valueOf() : 可以忽略, 对象类型默认valueOf会返回自身
        console.log( [10,20,30].valueOf() );// [10,20,30]
        console.log( new Number(10) );//10  valueOf() 默认只会对基本包装类型有效
        // b1.   toString() :  数组的toString() 本质是调用join()转成字符串
        console.log( [10,20,30] == '10,20,30' );//true
        console.log( [] == '' );//true
        console.log( [] == 0 );//true  (1) [].toString  (2) '' == 0 (3) 0 == 0
        // b2.   toString() :  对象的toString() 返回固定格式字符串  '[object Object]'
        console.log( {name:'张三'} == '[object Object]');//true
        console.log( {name:'李四'} == '[object Object]');//true

以下是针对2.4的面试题的坑

代码语言:javascript
复制
        console.log( [] == 0 );//true
        //这里我们要了解其他类型转Boolean为false的几种情况:0、-0、null、undefined、false、NaN、""
        //(1)  ![] 隐式规则转布尔类型  !Boolean([]) =  !true = false
        //(2)  flase == 0
        //(3)  Number(false) == 0   0 == 0
        console.log( ![] == 0 );//true  
        console.log( {} == 0 );//false    '[object Object]' == 0
        console.log( !{} == 0 );//true   原理同  ![] == 0   不存在调用toString() 本质是逻辑非表达式结果 与 0 比较       

2.5 x或y  都为引用类型。则直接比较两者地址,地址一致则为true,地址不一致则为false

代码语言:javascript
复制
        var arr1 = [10,20,30];
        var arr2 = arr1;//拷贝地址 赋值
        var arr3 = [10,20,30];
        //虽然arr1 arr2 arr3打印的时候,一模一样的。但是他们对应的堆地址不同(钱一样银行卡不一样 )
        console.log(arr1 == arr2);//true
        console.log(arr1 == arr3);//false
        console.log(arr2 == arr3);//false        

以下是针对2.5的面试题的坑

代码语言:javascript
复制
        console.log( [] == [] );//false   声明两个空数组,堆中地址不同
        //(1)左边   ![] = !true = false
        //(2)右边   [].toString = ''
        //(3)false (数字0) == ''(数字0)
        console.log( ![] == [] );//true   
        console.log( ![] == ![] );//true  两个逻辑非表达式比较  !true == !true   false == false

        //原理同上
        console.log(  {} ==  {} );//false
        //(1)左边 !{} = !true = false
        //(2)右边 {}.toString = '[object Object]'
        //(3) false (数字0) == '[object Object]' (数字NaN)
        console.log( !{} ==  {} );//false  
        console.log( !{} == !{} );//true

以下为特殊情况

代码语言:javascript
复制
        // null是原型链终点, 底层是堆地址起点 0x0000
        console.log( null == 0);//false   null不会转换 ,会直接用地址 和 0 比较
        //以上五种情况 只是对 == 运算符生效。 其他的比较运算符还是转number
        console.log( null >= 0);//true  Number(null) >= 0   0 >= 0
        console.log( null <= 0);//true  Number(null) <= 0   0 <= 0

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 01-js高级语法补充
    • 1.1-值类型与引用类型复习
      • ==1.2-参数传递==
        • 1.3-in关键字三个作用
          • 1.4-delete关键字两个作用
            • 1.5-比较运算符隐式转换
              • 1.复习隐式转换 : 运算符在运算的时候,如果两边的数据类型不一致,则会自动转成一致后运算。
              • 2. 特殊情况
              • 3. x == y: 比较运算符分为五种情况
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档