JavaScript- 变量声明

1、变量声明方式

   ES6变量声明使用let/const,其中最重要的两个特性:

    >块级作用域

    >不再具备变量提升

 

ES6

     {
       let _name ="aaa";
     }  

      console.log(_name);  //Uncaught ReferenceError: _name is not defined

  

    console.log(_name); // _name is not defined
    let _name = "zs";

 

ES5

 console.log(_name); //undefined
 let _name = "zs";

 

变量提升:

ES5-会存在变量提升,没有块级作用域,它的作用域分为两种:一个是全局作用域,另一个是函数作用域;

具体会在后续执行上下文环境中介绍

 

在ES6,我们需要使用let/const替换var ,let用来声明一个会被改变的变量;const来声明一个值不会被改变的变量,也就是常量。

当值为基础数据类型时,那么这里的值,就是指值本身。

而当值对应的为引用数据类型时,那么我这里说的值,则表示指向该对象的引用。这里需要注意,正因为该值为一个引用,只需要保证引用不变就可以,我们仍然可以改变该引用所指向的对象。

 当我们试图改变const声明的变量时,则会报错。

   const  C  = 'a';
          C = 'b';   // Assignment to constant variable. 可能你想赋值给了一个常数变量 但这个变量是不能改变的

 

数据类型:

基本数据类型:Strint、Number、Bollean、Undefined、Null、Symbol(ES6新增了解) 基本数据类型是一些简单数据,它们存在栈内存中。

引用数据类型:Array、Object   引用数据类型是保存在堆内存中的,在栈内存保存一个对堆内存中的引用(地址),所有javascript引用数据类型

                     的操作都是操作对象的引用而不是实际的对象。

可以理解为,栈内存中保存了一个地址,这个地址指向堆内存中的数据对象。

复制

 

基本数据类型

对于基本数据类型,如果进行复制,系统会自动为新的变量在栈内存中分配一个新值

 

 

引用数据类型

如果对于数组、对象这样的引用数据类型而言,复制的时候就会有所区别了:

系统也会自动为新的变量在栈内存中分配一个值,但这个值仅仅是一个地址。也就是说,复制出来的变量和原有的变量具有相同的地址值,指向堆内存中的同一个对象。

 

如果所示,执行了 var objCopy=obj 之后, obj 和 objCopy 具有相同的地址值,执行堆内存中的同一个实际对象。

 

深浅拷贝

   浅拷贝是拷贝一层,深层次的对象级别的就拷贝引用;深拷贝是拷贝多层,每一级别的数据都会拷贝出来;

  

 

var obj1 = {
            name: "xyc",
            features: {
                say: "hello",
                eat: "something"
            }
        }

 

声明一个函数

var shallowCopy = function(obj) {
  // 只拷贝对象
  if (typeof obj !== 'object') return;
  // 根据obj的类型判断是新建一个数组还是对象
  var newObj = obj instanceof Array ? [] : {};    //instanceof 用于判断一个变量是否某个对象的实例
  // 遍历obj,并且判断是obj的属性才拷贝
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = obj[key];
    }
  }
  return newObj;
}
        var obj2 = shallowCopy(obj1);
        obj2.features.eat = "anything";
        console.log(obj1.features.eat); // "anything"

        console.log(obj1 === obj2); // false浅copy 属性值独立,指向不同
        console.log(obj1.features === obj2.features); // true   浅copy一层copy ,下一级对象的指向堆内存数据对象是相同的

 

深copy

        var deepCopy = function (obj) {
            // 只拷贝对象
            if (typeof obj !== 'object') return;
            // 根据obj的类型判断是新建一个数组还是对象
            var newObj = obj instanceof Array ? [] : {};
            // 遍历obj,并且判断是obj的属性才拷贝
            for (var key in obj) {
                if (obj.hasOwnProperty(key)) {
                    // 当obj中嵌套对象时,再次调用该方法
                    newObj[key] = typeof obj[key] !== 'object' ? obj[key] : deepCopy(obj[key]);
                }
            }
            return newObj;
        }

 

 

看下属性与对象是否相同 ???

   var obj2 = shallowCopy(obj1);
        obj2.features.eat = "anything";
        console.log(obj1.features.eat); // "anything"

        console.log(obj1 === obj2); // false 
        console.log(obj1.features === obj2.features); // false

 

互相独立内存空间。。

 

粗暴的拷贝方式

    通过JSON.parse( JSON.stringify() )实现

 

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。(浅copy一种)

 Object.assign(target, ...sources);

 

参数:

  • target: 目标对象
  • sources: 源对象

 

        var obj1 = {
            name: "xyc",
            age: 25
        }

        var obj2 = Object.assign({},obj1);
        obj2.name="test"
        console.log(obj1 == obj2)  // false
     

 

内存声明周期,引用数据类型与堆内存

与其他语言不同,JS的引用数据类型,比如数组Array,它们值的大小是不固定的。引用数据类型的值是保存在堆内存中的对象。

JS不允许直接访问堆内存中的位置,因此我们不能直接操作对象的堆内存空间。

在操作对象时,实际上是在操作对象的引用而不是实际的对象。

因此,引用类型的值都是按引用访问的。

 

生命周期:

内存的生命周期大致分为三个步骤

     >JavaScript 在定义变量或者创建一个变量的时候,就完成了内存分配。

     >使用分配到的内存(读、写) 

     >不需要时将其释放归还

 

       var a = new Object(); //创建A的实例

       a.test = 'hello';

       a = null;  // 销毁对象

 

posted on 2019-04-27 12:18  Mc525  阅读(1139)  评论(0)    收藏  举报

导航