深挖对象和函数

一、对象

对象就是一个容器,容器中存储了若干个元素,这些元素都通过名称和值这种方式存储

  • 名称–>key 值–>value 键值对
  • 任何数据结构都无法超越对象的键值查找速度
  • key 的类型必须是字符型或者是symbol

通过对象的属性访问值,有两种方法

  1. obj.a=10; //key必须是字符,而且必须是确定的字符
  2. obj[“a”]=10; //key可以是任何类型,但是都会被隐式转换成字符串,也可以是变量
		var key="names";
        obj[key]="xie"; //如果给入的是变量,就会将变量的值作为对象的key
        obj.key="xie";// undefined 以点语法使用属性时,默认属性就是字符串,无法使用变量
        obj["key"]="xie";
        console.log(obj.key);

var obj={a:1,b:2};
//对象没有元素个数,也就是说对象没有长度,无法确定对象中存在的个数

  • 在其它语言中对象的存储是无序的,当遍历时对象的属性是随机遍历
  • 对于JS来说 属性是按照属性添加的先后顺序遍历的
prop是一个变量。用变量来遍历obj的属性时,要加[]
        for(var prop in obj){
            //判断某个属性是不是在obj中
            //遍历对象的属性名 按照添加属性顺序
            console.log(prop,obj[prop]);
        }
  	  var o={a:1,b:2};
      var o1=o; //将o的引用地址赋值给o1,
      o.a=10; //将对象中a属性的值修改
      //o={a:10,b:2}; 这是重新将另一个对象的引用对象地址给了o,所有现在的o!=o1
      console.log(o1);//控制台中的属性值顺序是按添加属性的顺序打印的,而点击△object后展出的顺序是按ASCII码排列的
     
      var o={a:1,b:2};
      var o1=o;
      console.log(o);  //第一次打开浏览器时,打印的是引用地址,点开△object才会取堆中拿到这个引用地址,值也会打印,刷新页面,先打印缓存中的内容,但花括号中a的值还是1,而点△object从堆中取值a为10;
      o.a=10;
堆栈
  • 栈相当于内存,脑干 ;堆相当于硬盘,大脑
  • 变量名存储在栈中,在栈中变量名通常对应一个值,这个值的类型有很多种
  • 只有字符型/数值型/布尔型/undefined/symbol型直接可以以值的方式存储在这个栈的变量名对应之后
  • 除上述外其它类型都是引用类型,引用类型都存储在堆中,并且在堆中以一个引用地址来存储值
  • 这种引用类型在栈中使用变量名后面存储堆中对应的引用地址

//单链表 二叉树

var o={value:1,left:{value:2,left:{value:4},right:{value:5}},right:{value:3,left:{value:6},right:{value:7}}}
内存泄漏和垃圾回收
var o={a:1};
o={a:2};//{a:1}成垃圾 

内存泄漏
指在运行过程中不断创建对象,并且这些对象不再做垃圾回收,就会造成内存泄漏
垃圾回收
当一个对象不再使用时,将这个对象的所有引用地址赋值的所有变量全部设置为null,当内存超出一定值,系统会自动将这些没有引用的对象回收

		var o={a:1};
        o=null;//解除引用关系
        o={a:2};
        //dispose()

垃圾管理池 flag
delete

  		   var o={a:1,b:2};
           delete o.a;
           console.log(o);//{b:2}

       		 var a=10;
       		 console.log(window.a);
      		 delete window.a;//无法删除  所有变量都是window属性,但是无法使用delete属性
       		 console.log(a);

深复制和浅复制

  • 对象浅复制 只复制一层,复制c时复制的是引用地址,无法将地址中的值复制到另一个对象
  • 当把对象的每一层都完成复制,就叫做对象深复制
浅复制
1. var o={a:1,b:2,c:{value:2}};
        var o1={};
        for(var prop in o){
            o1[prop]=o[prop];
        }

		 o.a=10;
        o.c.value=100;
        console.log(o1);  //o1中的c值变为100
2. var o1={};
        Object.assign(o1,o);//Object.assign(目标,源)  浅复制
        o.a=10;
        o.c.value=100;
        console.log(o1);
3.var o1=Object.assign({},o);//把o复制到空对象上,并且返回给o1
对象深复制
		var obj={
            a:1,b:2,c:3,d:{e:10},f:undefined
        }
        var o=JSON.parse(JSON.stringify(obj));
        obj.d.e=100;
        console.log(o);  //e的值不会改变

二、函数

创建函数
  • 函数就是语句块,在适当的时机执行函数,就可以完成对于该语句块的执行
  • 函数要简洁、功能单一
  • 格式:function 函数名(参数1,参数2…){ 语句块 }
1. 命名函数的创建
   function fn(){
            console.log("aaa");
       }
//函数基于对象创建,所以函数也是方法,typeof时函数是function
//函数存在堆中,当函数所在的script标签被执行时,先将函数放在堆中,然后再栈中创建变量(函数名)引用堆中的函数地址
//引用完成后,函数名的变量就会自动生成,生成后再执行当前script后面的语句
//命名函数可以写在当前标签的任意位置,都可以在任意位置调用

2.匿名函数 
当代码执行到这里时,创建一个匿名函数赋值给一个变量
只有定义以后才可以调用,之前是不可以的
 var fn1=function(){
              console.log("bbb");
          }
 fn1();

 自执行匿名函数
        (function(){
            console.log("aaa");
        })();

           ~function(){
                console.log("aaa");
            }();

            +function(){
                console.log("aaa");
            }();

3.构造函数创建法   
里面的所有内容都是字符串,没有提示,其次函数再创建时会将字符串转换为代码,消耗极大
使用环境其中之一:后端给前端一段js字符串代码取执行
            var  fn=new Function("a","b","console.log(a+b)");

            function fn(a,b){
                console.log(a+b);
            }
拷贝:
		   for(var prop in obj){
                if(typeof obj[prop]==="function"){
                    obj[prop]=obj[prop].toString();
                }
            }
            console.log(JSON.stringify(obj));
            fn(5,8);
函数作用域
  • 全局变量 当在函数内部使用全局变量,被调用一次变量修改一次
  • 局部变量 当函数执行完成后,局部变量会自动销毁。局部变量无法根据函数执行次数保留累计变量值
		var a=3;
        function fn(c){ 
        //如果函数中定义了与外部的全局变量相同的名称时,当前函数中无法直接使用全局变量
            //c是参数,也是局部变量
            //var a;  变量提升
            var a=5;
            console.log(a+window.a+fn.a); //5+3+10 局部优先
        }
        fn.a=10;
        fn();
1.		 var a=10;
       function fns(){
           if(a<10) var a=10;
           else console.log(a);
       }
       fns();//undefined   在函数中只要出现var,变量提升到函数顶部
2.    var a=5;
      var  a=function(a,a){
           console.log(a);
           var a=7;
           console.log(a);
       }
       a(4,6);   //报错
3.function fns(o){
       o=100;
   }
   var a=10;
   fns(a);
   console.log(a); //10
4. function fns(o){
       o={a:2};
   }
  var a={a:1};
   fns(a);
   console.log(a);//  {a:1}   将参数a带入函数的适合相当于 var o=a;然后再给o重新赋值{a:2};
5.function fns(o){
       o.a=10;
   }
   var a={a:1};
   fns(a);
   console.log(a);
6. var a = {n: 1}
   var b = a
   a.x = a = {n: 2}
  求 a.n  b.n    a.x    b.x
      2     1      undefined   {n:2}
this指向
1.对象属性上的this和对象中函数中的this
 var a=10;
  var obj={
      // 写在属性上的this,一边创建该对象,一边设置值,对象还没有创建完成,所以this仍然指向window
      a:this.a,
      b:function(){
          // console.log(a);//全局a
          // console.log(obj.a);
          // 写在函数中的this,函数调用时,对象本身一定是创建完成的,谁调用当前函数,this就是谁
          console.log(this.a);//谁调用当前b函数,this就是谁
      },
      c:{
          a:this.a,
          b:function(){
              console.log(this.a);
          }
      }
  }

var o=obj;
obj={c:10};
o.b(); //10  undefined 10   this指对象o
o.c.b();   //10 10   this指c对象
2.单函数内部的this指向windows
3.回调函数中的this
  》不管回掉函数中原this指向什么,现在this统一指向window
  》当使用arguments完成回调函数的执行时,不管回调函数中this原指向什么,在这里统一指向当前的arguments
   		function fn1(f){
              f();//回调  ,不管回调的函数中原this指向什么,现在统一指向window
          }
          function fn3(f){
              arguments[0]();//当使用arguments完成回调函数的执行时,不管回调函数中this原指向什么,在这里统一指向当前的arguments
          }

         var obj={
             a:1,
             fn2:function(){
                 console.log(this);//window
             }
         }
          obj.fn2();  //this指向obj
          fn1(obj.fn2);  //this指向window
          fn3(obj.fn2); //this指向Arguments
参数
  • 函数中的参数是局部变量,可以通过执行函数时将值传递给函数,赋予对应位置的参数
  • 参数分为形参和实参
  • 函数定义中的参数叫形参,执行函数传入的数据叫实参
  • 实参赋值给形参时,按照实际顺序一一赋值
  • 参数是弱类型,ES5中参数不能设置初始值,参数必须按顺序给入,参数在传递时如果不需要填入时,用逗号分隔
  • 函数的长度为形参数量 函数名.length
  • 参数如果有不定数量,在ES5中无法设置不定数量,但是在ES5函数中会自动创建一个arguments
  • 实参的数量arguments.length
求最大值
  function max(){
                // console.log(arguments.length);//实参的数量
                if(arguments.length===0) return undefined;
                if(arguments.length===1) return arguments[0];
                var max=arguments[0];
               for(var i=1;i<arguments.length;i++){
                  max=max<arguments[i] ? arguments[i] : max;
               }
               console.log(max);
            }
            max(5,6,7,10,20);
       function fn2(a,b){
             console.log(arguments.callee);//当前执行的函数  fn2
             console.log(arguments.callee.caller);//在那个函数中执行了fn2
             console.log(fn2.caller);
         }
         fn1(fn2);
         结果:
         ƒ fn2(a,b){
             console.log(arguments.callee);//当前执行的函数  fn2
             console.log(arguments.callee.caller);//在那个函数中执行了fn2
             console.log(fn2.caller);
         }
 		ƒ fn1(f){
             f(3,5);
         }
 		ƒ fn1(f){
             f(3,5);
         }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值