点击上方“IT平头哥联盟”,选择“置顶或者星标”

一起进步~

面试的时候我们经常会被问答js的数据类型。大部分情况我们会这样回答包括:
1.基本类型(值类型或者原始类型): Number、Boolean、String、NULL、Undefined以及ES6的Symbol
2.引用类型:Object、Array、Function、Date等
作者曾经也是这样回答的,并且一直觉得没有什么问题。那么面试官问你Js数据类型时,他想知道什么呢?

1 、在内存中的位置不同

  • 基本类型: 占用空间固定,保存在栈中

  • 引用类型:占用空间不固定,保存在堆中

栈(stack)为自动分配的内存空间,它由系统自动释放;使用一级缓存,被调用时通常处于存储空间中,调用后被立即释放。堆(heap)则是动态分配的内存,大小不定也不会自动释放。使用二级缓存,生命周期与虚拟机的GC算法有关

当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁了。因此,所有在方法中定义的变量都是放在栈内存中的;栈中存储的是基础变量以及一些对象的引用变量,基础变量的值是存储在栈中,而引用变量存储在栈中的是指向堆中的数组或者对象的地址,这就是为何修改引用类型总会影响到其他指向这个地址的引用变量。

当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(因为对象的创建成本通常较大),这个运行时数据区就是堆内存。堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见),则这个对象依然不会被销毁,只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。

2、赋值、浅拷贝、深拷贝

  • 对于基本类型值,赋值、浅拷贝、深拷贝时都是复制基本类型的值给新的变量,之后二个变量之间操作不在相互影响。

  • 对于引用类型值,

赋值后二个变量指向同一个地址,一个变量改变时,另一个也同样改变;

浅拷贝后得到一个新的变量,这个与之前的已经不是指向同一个变量,改变时不会使原数据中的基本类型一同改变,但会改变会原数据中的引用类型数据

深拷贝后得到的是一个新的变量,她的改变不会影响元数据

- 和原数据是否指向同一对象 第一层数据为基本数据类型 原数据中包含子对象
赋值 改变会使原数据一同改变 改变会使原数据一同改变
浅拷贝 改变不会使原数据一同改变 改变会使原数据一同改变
深拷贝 改变不会使原数据一同改变 改变不会使原数据一同改变
    var obj1 = {        'name' : 'zhangsan',        'age' :  '18',        'language' : [1,[2,3],[4,5]],    };    var obj2 = obj1;    var obj3 = shallowCopy(obj1);    function shallowCopy(src) {        var dst = {};        for (var prop in src) {            if (src.hasOwnProperty(prop)) {                dst[prop] = src[prop];            }        }        return dst;    }    obj2.name = "lisi";    obj3.age = "20";    obj2.language[1] = ["二","三"];    obj3.language[2] = ["四","五"];    console.log(obj1);      //obj1 = {    //    'name' : 'lisi',    //    'age' :  '18',    //    'language' : [1,["二","三"],["四","五"]],    //};    console.log(obj2);    //obj2 = {    //    'name' : 'lisi',    //    'age' :  '18',    //    'language' : [1,["二","三"],["四","五"]],    //};    console.log(obj3);    //obj3 = {    //    'name' : 'zhangsan',    //    'age' :  '20',    //    'language' : [1,["二","三"],["四","五"]],    //};

2.1、浅拷贝

数组常用的浅拷贝方法slice,concat,Array.from() ,以及es6的析构

var arr1 = [1, 2,{a:1,b:2,c:3,d:4}];var arr2 = arr1.slice();var arr3 = arr1.concat();var arr4 = Array.from(arr1);var arr5 = [...arr1];arr2[0]=2;arr2[2].a=2;arr3[0]=3;arr3[2].b=3;arr4[0]=4;arr4[2].c=4;arr5[0]=5;arr5[2].d=5;// arr1[1,2,{a:2,b:3,c:4,d:5}]// arr2[2,2,{a:2,b:3,c:4,d:5}]// arr3[3,2,{a:2,b:3,c:4,d:5}]// arr4[4,2,{a:2,b:3,c:4,d:5}]// arr5[5,2,{a:2,b:3,c:4,d:5}]

对象常用的浅拷贝方法Object.assign(),es6析构

var obj1 = {    x: 1,     y: {        m: 1    }};var obj2 = Object.assign({}, obj1);console.log(obj1) //{x: 1, y: {m: 1}}console.log(obj2) //{x: 1, y: {m: 1}}obj2.x=2;obj2.y.m = 2; //修改obj2.y.mconsole.log(obj1) //{x: 1, y: {m: 2}}console.log(obj2) //{x: 2, y: {m: 2}}

我们自己实现一个浅拷贝

var obj = { a:1, arr: [2,3] };var shallowObj = shallowCopy(obj);var shallowCopy = function(obj) {    // 只拷贝对象    if (typeof obj !== 'object') return;    // 根据obj的类型判断是新建一个数组还是对象    var newObj = obj instanceof Array ? [] : {};    // 遍历obj,并且判断是obj的属性才拷贝    for (var key in obj) {        if (obj.hasOwnProperty(key)) {            newObj[key] = obj[key];        }    }    return newObj;}

2.2、深拷贝

比较简单粗暴的的做法是使用JSON.parse(JSON.stringify(obj))

var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}]var new_arr = JSON.parse( JSON.stringify(arr) );new_arr[4].old=4;console.log(arr); //['old', 1, true, ['old1', 'old2'], {old: 1}]console.log(new_arr); //['old', 1, true, ['old1', 'old2'], {old: 4}]

JSON.parse(JSON.stringify(obj)) 看起来很不错,不过MDN文档 的描述有句话写的很清楚:

undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。

但是在平时的开发中JSON.parse(JSON.stringify(obj))已经满足90%的使用场景了。
下面我们自己来实现一个

var deepCopy = function(obj) {    if (typeof obj !== 'object') return;    var newObj = obj instanceof Array ? [] : {};    for (var key in obj) {        if (obj.hasOwnProperty(key)) {            newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];        }    }    return newObj;}

3、参数的传递

所有的函数参数都是按值传递。也就是说把函数外面的值赋值给函数内部的参数,就和把一个值从一个变量赋值给另一个一样;

  • 基本类型

var a = 2;function add(x) { return x = x + 2;}var result = add(a);console.log(a, result); // 2 4
  • 引用类型

function setName(obj) {  obj.name = 'laowang';  obj = new Object();  obj.name = 'Tom';}var person = new Object();setName(person);console.log(person.name); //laowang

很多人错误地以为在局部作用域中修改的对象在全局作用域中反映出来就是说明参数是按引用传递的。
但是通过上面的例子可以看出如果person是按引用传递的最终的person.name应该是Tom。
实际上当函数内部重写obj时,这个变量引用的就是一个局部变量了。而这个变量会在函数执行结束后销毁。(这是是在js高级程序设计看到的,还不是很清楚)

4、判断方法

基本类型用typeof,引用类型用instanceof

特别注意typeof null"object"null instanceof Objecttrue;

console.log(typeof "Nicholas"); // "string"console.log(typeof 10);         // "number"console.log(typeof true);       // "boolean"console.log(typeof undefined);  // "undefined"console.log(typeof null);      // "object"var items = [];var obj = {};function reflect(value){  return value;}console.log(items instanceof Array); // true;console.log(obj instanceof Object); // true;console.log(reflect instanceof Function); // true;

Object.prototype.toString.call([]).slice(8, -1)有兴趣的同学可以看一下这个是干什么的

5、总结

本文原载于SegmentFault专栏"前端小将"

整理编辑:SegmentFault 链接:https://segmentfault.com/a/1190000018745719

- end -

用心分享 一起成长 做有温度的攻城狮

每天记得对自己说:你是最闷骚的!

热门推荐

浅谈easy-mock 最好的备胎没有之一

前端面试坑点,都在这里了~

深入浅出 JavaScript 中的For循环之详解

从高阶函数到库和框架之优秀前端进阶~

PNG图片压缩无损,但解析原理呢?

各种资源免费共享:简历模板、面试题等

为什么说Suspense是一种巨大的突破?

跳槽?前端面试知识点目录大全~

localStorage也能像cookie设置一个过期时间?

都看到这里了,给个“看”再走呗~

js var是什么类型_面试官问你JS基本类型时他想知道什么?相关推荐

  1. obj: object是什么意思_面试官问你JavaScript基本类型时他想知道什么?

    本文原载于SegmentFault专栏"前端小将" 整理编辑:SegmentFault 面试的时候我们经常会被问答js的数据类型.大部分情况我们会这样回答包括: 1.基本类型(值类 ...

  2. 后处理程序文件大小的变量_【每日一题】(17题)面试官问:JS中事件流,事件处理程序,事件对象的理解?...

    关注「松宝写代码」,精选好文,每日一题 作者:saucxs | songEagle 2020,实「鼠」不易 2021,「牛」转乾坤 风劲潮涌当扬帆,任重道远须奋蹄! 一.前言 2020.12.23 立 ...

  3. 面试官问:JS的this指向

    写于2018年12月25日,发布在掘金上阅读量近一万,现在发布到微信公众号申明原创. 前言 这是面试官问系列的第四篇,旨在帮助读者提升JS基础知识,包含new.call.apply.this.继承相关 ...

  4. 面试官问:JS的继承

    原文作者若川,掘金链接:https://juejin.im/post/5c433e216fb9a049c15f841b 写于2019年2月20日,现在发到公众号声明原创,之前被<前端大全> ...

  5. java执行sql文件_面试官问你MyBatis SQL是如何执行的?把这篇文章甩给他

    初识 MyBatis MyBatis 是第一个支持自定义 SQL.存储过程和高级映射的类持久框架.MyBatis 消除了大部分 JDBC 的样板代码.手动设置参数以及检索结果.MyBatis 能够支持 ...

  6. .jar中没有主清单属性_面试官问:为什么SpringBoot的 jar 可以直接运行?

    点击上方蓝色字体,选择"设为星标" 优质文章,及时送达 来源 | https://urlify.cn/uQvIna SpringBoot提供了一个插件spring-boot-mav ...

  7. sql参数化还是被注入了_面试官问你 SQL 注入攻击了吗?

    目录 为什么要聊 SQL 注入攻击? 什么是 SQL 注入攻击? 如何进行 SQL 注入攻击? 如何防范? 常见面试题 瞎比比 为什么要聊 SQL 注入攻击? 我这人有个想法,就是不管自己跳不跳槽,每 ...

  8. 16 bit float 存储_面试官问我存储金额应该用哪种数据类型,我竟这样回答

    前言 ​ 最近在面试时,碰到这样一个问题:在问到项目部分时,面试官问我:你的项目中用到的分数.金额之类的数字是用的什么数据类型? 我没有过多思考脱口而出:double!随后面试官又问:为啥不用floa ...

  9. redis怎么修改_面试官问我Redis事务,还问我有哪些实现方式

    ❝ 「第12期」 距离大叔的80期小目标还有68期,今天大叔要跟大家分享的内容是 -- Reids中的事务.同样,这也是redis中重要指数为四颗星的必备基础知识点.下面一起来了解一下吧. ❞ 相信大 ...

最新文章

  1. Memcached安装以及PHP的调用
  2. XML 命名空间概述
  3. R构建指数回归模型(Exponential Regression)
  4. Xamarin图表开发基础教程(1)
  5. ceph pg_num 数值计算
  6. Facebook上的一道题,超过50万的评论和1万3500次分享
  7. linux---基础04
  8. ubuntu18.04安装unity tweak tool
  9. 上新了! 热门开源 AutoML 工具 NNI 2.0 来袭!
  10. marlin固件烧录教程_marlin固件中文(marlin固件下载)
  11. What is a computer?
  12. 算法学习:插值型求积公式
  13. IMDB评分排名算法
  14. 读《枪炮,病菌和钢铁》
  15. 九章算法笔记D2-坐标型动态规划
  16. CC2530简单功能实现
  17. 毕业季!清北毕业生都去哪了?
  18. 在FL Studio中如何制作人声切片(Vocal Chops)
  19. 双色球--最多2个号码相同的内幕
  20. 3.5.2 使用Badboy录制Web性能测试脚本

热门文章

  1. 关于《ASP.NET MVC企业级实战》
  2. 总结 15/4/23
  3. 《FilthyRichClients》读书笔记(一)-SwingのEDT
  4. ubuntu 11.10 下network proxy 的设置问题
  5. 采用docker安装部署Nginx
  6. 2-6 刮刮乐和双色球
  7. 7-4 组从配置-操作
  8. java删除有序数组中的重复元素_算法刷刷刷Leetcode第26题删除排序数组中的重复项...
  9. 计算机毕业设计中用python神经网络编程实现手写数字识别
  10. java代码生成apk_android – 如何通过java代码以编程方式生成apk文件