唯心主义蠢货的[js知识总结] 变量部分(变量类型 深浅拷贝 变量提升)

本文主要是介绍唯心主义蠢货的[js知识总结] 变量部分(变量类型 深浅拷贝 变量提升),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

变量

文章大纲
在这里插入图片描述

1.变量类型

js的变量类型有两种

  • 基本类型: null undefined number boolean string symbol(ES6)

    是存放在栈中的简单数据段,按值储存,所以可以按值访问,大小由类型确定,内存空间大小可以分配

  • 引用类型: object(function array 都是基于object拓展出来的 typeof arr == ‘object’,涉及到原型链部分)

    数据存放在堆中,在栈中保存对象的引用地址

在这里插入图片描述

深拷贝 浅拷贝

  • 浅拷贝

    即复制引用类型的数据时,只是简单的将地址拷贝过来,两块地址指向同一块堆内存,所以改a即改b

    实现方式

    var a  = {key1: {m:123,h:33},key2: 'b'
    }
    var b = {};/*对于对象来说*/
    //1.直接拷贝对象属性
    function copy(x,y){Object.keys(x).forEach((key) => { y[key] = x[key]; })
    }
    let arr = [1,{ my: 'dog' } ];
    let arr2;
    copy(arr,arr2);
    arr2[1].my = 'asaa';
    console.log(arr2);//2.调用对于assign函数  对于只有一层的对象进行深拷贝,但是对于第二层  第三层会复制对象的地址
    b = Object.assign({},obj)
    //如a.key2 会被深拷贝, a.key1 会被浅拷贝/*对于数组来讲*/
    //1.Array.prototype.concat() // 连接空值返回一个浅拷贝数组
    let arr = [1,{ my: 'dog' } ];
    let arr2 = arr.concat();
    arr2[1].my = 'pig';
    console.log(arr);//2.Array.prototype.slice() // 切片从0开始  返回一个浅拷贝数组
    let arr = [1,{ my: 'dog' } ];
    let arr2 = arr.slice(0);
    arr2[1].my = 'pig';
    console.log(arr);
    
  • 深拷贝

    如果我们想要两者不建立联系,则可以直接复制属性

    var a  = {key1: {m:123,h:33},key2: 'b'
    }
    var b = {};//对于只有一层的对象 直接用assign函数
    b = Object.assign({},obj);//使用递归进行实现
    function copy(x){//判断是否为数组let y = Array.isArray(x)?[] : {};for(let i in x){//判断当前项是否为对象  如果是则深复制if(typeof x[i] === 'object'){y[i] = copy(x[i]);}//如果否 则浅复制else{y[i] = x[i];}}return y
    }
    b = copy(a);
    a.key1.m = 'c';
    console.log(b);
    

2.变量提升

解释(javascript并不是严格的自上而下执行的语言。)

当没有定义变量时,输出会报错,当定义变量时,当前变量会提升到可执行区域的最上方,但暂时不进行赋值,且当变量和函数重名时,函数的优先级高于变量。

即 函数自动提升到最上方; 变量的定义提升到最上方,但是赋值语句不变

原因

js在编译阶段会搜集所有的变量声明,并提前进行声明,但不会改变其他语句的执行顺序。

1.变量的定义

即 var a = 2;等价于 var a;(编译阶段) a=2(运行阶段)

2.当函数出现时
  • 当函数和变量名相同时,函数是js的第一公民,所有以函数名为准

在这里插入图片描述

  • 当函数定义重复时,以后边的为准,即后面的声明替换掉前面的声明

在这里插入图片描述

  • 对于函数表达式 var x = function () { … } 与对变量的定义相同,报error,var x; x = function(){}

在这里插入图片描述

3.let/const 出现的情况

let/const 统一也会进行变量提升,但是在执行对应定义语句之前,是不能进行访问的,所以提前输出会出现not defined的状况,即代码编译到let/const执行定义之前,对应变量无法访问,称为时间死区。

一些题目

  • 1
  function f(a){console.log(a);//(){}var a = 2;console.log(a);//2function a(){};console.log(a);//2}f(1);/* 等价于function f(a){var a;var a = (){};//函数提升到这一部分console.log(a);a = 2;console.log(a);console.log(a);}f(1); */
  • 2
function test() {console.log(a);  // undefinedconsole.log(foo()); // 2var a = 1;function foo() {return 2;}
}test();/* 等价于
function test() {var a;function foo() {return 2;}console.log(a);  // undefinedconsole.log(foo()); // 2a = 1;
}test();*/
  • 3 注意 foo = (){ … } 但是 foo() = 函数体里的内容
function test() {console.log(foo); // (){}console.log(bar); // undefinedvar foo = 'Hello';console.log(foo); // 'hello'var bar = function () {return 'world';}function foo() {return 'hello';}
}test();/* 等价于
function test() {var foo;var bar;function foo() {return 'hello';}console.log(foo);console.log(bar);foo = 'Hello';console.log(foo);bar = function () {return 'world';}}test();

思考

为什么string是基本类型,但是还可以用indexof或者其他的一些方法

原始值被当作构造函数创建的一个对象来使用时, JS 会将其转换为一个对象,以便其可以使用对象的特性(如方法),而后抛弃对象性质,并将它变回到原始值

基本包装类型 的概念。除了 Object Array 等引用类型外,其实还有三种特殊的引用类型 String Number 和 Boolean,方便我们操作与其对应的基本类型,而它们就是基本包装类型。str 作为一个基本类型是没有 length 属性的,但是它的基本包装类型 String 有啊,其实在执行 console.log(str.length) 这段代码时,事情的经过是这样的:
创建String类型的一个实例
在实例上调用指定的方法
销毁这个实例

// java 中的拆箱封箱操作,基本类型和引用类型转换,js中省略了这一步

let str = "1353";
console.log(str.length);// 等于
let str_obj = new String(str);
str_obj.length;
str_obj = null;

最后引用一段《Javascript启示录》中的话:
在针对字符串、数字和布尔值使用字面量时,只有在该值被视为对象的情况下才会创建实际的复杂对象。换句话说,在尝试使用与构造函数关联的方法或检索属性(如var len = ‘abc’.length) 之前,一直在使用原始数据类型。当这种情况发生时,Javascript 会在幕后为字面量值创建一个包装器对象,以便将该值视为一个对象。调用方法以后,Javascript 即抛弃包装器对象,该值返回字面量类型。这就是字符串、数字、布尔值被认为是原始数据类型的原因。

既然string有基本包装对象,那么numer是否有原型呢,写出可以正确执行 console.log((5).add(4).minus(8))的操作

Number.prototype.add = function(number){if(typeof number !== "number"){return new Error("输入数字");}return this.valueOf() + number;
}
Number.prototype.minus = function(number){if(typeof number !== "number"){return new Error("输入数字");}return this.valueOf() - number;
}

那如何实现Calc(2).add(5).minus(6)

借用上面的基本包装类型,然后进行使用

Number.prototype.add = function(number){if(typeof number !== "number"){return new Error("输入数字");}return this.valueOf() + number;
}
Number.prototype.minus = function(number){if(typeof number !== "number"){return new Error("输入数字");}return this.valueOf() - number;
}
Number.prototype.print = function(){console.log("result"+this.valueOf());
}console.log((5).add(4).minus(8));
function Calc(n){this.result = n;return this.result;
}Calc(2).add(4).minus(5).print();

也可以通过把Calc当做入口函数,在内部封装具体prototype,然后new 一个对象 暴露原型对象;

unction Calc(n){function calc(){this.result = n;}calc.prototype.add = function(x){this.result += x;return this;}calc.prototype.minus = function(y){this.result -= y;return this;}calc.prototype.print = function(){console.log('result='+this.result);}   return new calc(n);
}Calc(2).add(4).minus(5).print();

https://www.cnblogs.com/Lumia1020/p/5321618.html

这篇关于唯心主义蠢货的[js知识总结] 变量部分(变量类型 深浅拷贝 变量提升)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/207095

相关文章

C++中零拷贝的多种实现方式

《C++中零拷贝的多种实现方式》本文主要介绍了C++中零拷贝的实现示例,旨在在减少数据在内存中的不必要复制,从而提高程序性能、降低内存使用并减少CPU消耗,零拷贝技术通过多种方式实现,下面就来了解一下... 目录一、C++中零拷贝技术的核心概念二、std::string_view 简介三、std::stri

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

一文全面详解Python变量作用域

《一文全面详解Python变量作用域》变量作用域是Python中非常重要的概念,它决定了在哪里可以访问变量,下面我将用通俗易懂的方式,结合代码示例和图表,带你全面了解Python变量作用域,需要的朋友... 目录一、什么是变量作用域?二、python的四种作用域作用域查找顺序图示三、各作用域详解1. 局部作

Nginx Location映射规则总结归纳与最佳实践

《NginxLocation映射规则总结归纳与最佳实践》Nginx的location指令是配置请求路由的核心机制,其匹配规则直接影响请求的处理流程,下面给大家介绍NginxLocation映射规则... 目录一、Location匹配规则与优先级1. 匹配模式2. 优先级顺序3. 匹配示例二、Proxy_pa

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

使用Python获取JS加载的数据的多种实现方法

《使用Python获取JS加载的数据的多种实现方法》在当今的互联网时代,网页数据的动态加载已经成为一种常见的技术手段,许多现代网站通过JavaScript(JS)动态加载内容,这使得传统的静态网页爬取... 目录引言一、动态 网页与js加载数据的原理二、python爬取JS加载数据的方法(一)分析网络请求1

MySQL基本查询示例总结

《MySQL基本查询示例总结》:本文主要介绍MySQL基本查询示例总结,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Create插入替换Retrieve(读取)select(确定列)where条件(确定行)null查询order by语句li

java变量内存中存储的使用方式

《java变量内存中存储的使用方式》:本文主要介绍java变量内存中存储的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、变量的定义3、 变量的类型4、 变量的作用域5、 内存中的存储方式总结1、介绍在 Java 中,变量是用于存储程序中数据

VSCode中配置node.js的实现示例

《VSCode中配置node.js的实现示例》本文主要介绍了VSCode中配置node.js的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一.node.js下载安装教程二.配置npm三.配置环境变量四.VSCode配置五.心得一.no

Linux区分SSD和机械硬盘的方法总结

《Linux区分SSD和机械硬盘的方法总结》在Linux系统管理中,了解存储设备的类型和特性是至关重要的,不同的存储介质(如固态硬盘SSD和机械硬盘HDD)在性能、可靠性和适用场景上有着显著差异,本文... 目录一、lsblk 命令简介基本用法二、识别磁盘类型的关键参数:ROTA查询 ROTA 参数ROTA