小米技术社区
小米技术社区管理员 关于小米

27岁,山西运城人,职业电商经理人,前端开发工作者,从事过网站建设、网络推广、SEO、SEM、信息流推广、二类电商、网络运维、软件开发,等相关电商工作,经验较为丰富,小米技术社区致力于为广大从事Web前端开发的人员提供一些力所能及的引导和帮助 ...[更多]

E-mail:mzze@163.com

Q Q:32362389

W X:xiaomi168527

小米技术社区大牛王飞 关于王飞

27岁,山西运城人,职业电商经理人,网络工程师兼运维,从事过运营商网络建设,企业网络建设、优化。数据中心网络维护等通过,经验丰富,座右铭:当自己休息的时候,别忘了别人还在奔跑。 ...[更多]

E-mail:wf_live@126.com

Q Q:3940019

微博:王小贱ss

小米技术社区设计小艳 关于小艳

大于花一样的年龄,河南郑州是我家,2010年在北京接触团购网,2011年进入天猫淘宝一待就是四年,如今已经将设计走向国际化(ps:误打误撞开始进入阿里巴巴国际站的设计,嘿嘿)五年电商设计,丰富经验,从事过天猫淘宝阿里各项设计,店铺运营,产品拍摄;我将我的经历与您分享是我的快乐!座右铭:越努力越幸运! ...[更多]

E-mail:97157726@qq.com

Q Q:97157726

标签云
精品推荐
  • 什么是闭包?js闭包的2个最大用途以及注意事项

    什么是闭包?js闭包的2个最大用途以及注意事项

    各种专业文献上的"闭包"(closure)定义非常抽象,很难看懂。简单的说,闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因……
    134人已经看过了
您的位置:首页 > 前端开发 > Javascript > 原生JS

5第四阶段13 5函数表达式-回调函数-对象Object.assign-js垃圾回收

分类: 原生JS40个赞

//函数表达式  变量的形式定义的  以下2种方式可以被打印出来(不能两个一起)

/* let sayHi = function(){
    console.log("hello")
}
console.log(sayHi)
//函数也是可以赋值的
let b= sayHi;
console.log(b) */
/* function say(){
    console.log("nihao")
}
console.log(say */

//这两种形式有什么不同? 函数表达式调用不能写在前面,而原生的函数定义可以写在任何位置,因为js一开始会把所有的函数表达式当初一个模块先解析
//sayHi1()
let sayHi1 = function(){
    console.log("hello")
}
//和
say1()
function say1(){
    console.log("hello")
}

//1.箭头函数

let func =(arg1,arg2,arg3)=> expression;
//相当于

let func2 = function(arg1,arg2,arg3){
    return expression
}

//箭头函数实战
let func3 = (a,b) => console.log(a+b);
func3(1,2)

let func4 = name => console.log(name+"你好")  //只有一个参数的时候可以省略括号
func4("小米")

let func5=() => console.log("你好func5")   //如果没有参数的时候必须写括号
func5()

//所以html中回调函数的匿名函数的表达方式可以换为
/* ask("老乡,要不要一起学习",function(){alert("太好了")},function(){alert("那下次吧!")})
换为
ask("老乡,要不要一起学习",()=>alert("太好了"),()=>alert("那下次吧!")) */


//3.对象  属性和json一样是键:值

let user = new Object();
let key = "bag"; //对象灵活的方式,可以直接写变量值调用; 注意bag是文本型
let key1 = "bag1";
console.log(typeof user)
let person = {
    name:"小米",
    age:18,
    gender:"yao",
    isGay:true,
    "like birds":123, //如果是两个单词就必须要双引号,一个也可以加也可以不加
    say:()=>{console.log(person.name)},
    [key]:5, //计算属性,比较少用,上面key变量的值是bag
    [key1 + "good"]:6
}
console.log(person.bag) //可以直接调用bag
console.log(person.bag1good) //可以复杂一点
console.log(typeof person)
person.isAdmin = true; //可以在外部添加值
console.log(person.isAdmin)
delete person.isAdmin; //删掉值
console.log(person.isAdmin)
console.log(person["like birds"]) //索引号调用

//常量对象的值是可以被被修改的,注意,常量不能被修改,只是对象的值可以被修改 
const person1 = {
    name:"小米",
    age:18,
    gender:"yao",
    isGay:true,
    "like birds":123,   //如果是两个单词就必须要双引号,一个也可以加也可以不加
}
person1.age ="28";
console.log(person1.age)

function makeUser (name1,age1) {
    return {
        name1,  //也可写成name1:name1,这是简写
        age1
    }
}
let user1= makeUser("这是张三",18);
console.log(user1)

//判断对象是否有某个属性 因为javascript的对象属性可以随时添加删除,可能工程大了忘记了
console.log(person.height === undefined) //结果为true  这种方法不准确,如果有个对象属性是height,他的值是undefined,他也是true,所以这种方法不准
//用in操作可以避免上面的问题  in操作符判断一个属性在不在对象的方法
console.log("age" in person) //结果为true
console.log("dd" in person) //结果为false

//对象怎么遍历循环
for (const key in person) {
   console.log(key)  //打印person对象所有的属性
   console.log(person[key]) //打印person所有对象的值
}
//对象的整数属性  会从小到大排列

let codes = {
    "49":"德国",
    "21":"美国",
    "33":"英国",
    "94":"法国",
    "1":"中国"
}
for (const key in codes) {
    console.log(key)
    console.log(codes[key])  //我们发现输出中国在第一,按顺序排的,这是他的对象整数属性,如果必须要按照顺,可以在属性前+任何东西,让他不是整数
 }
//对象的复制问题
 let codes1= codes; //复制了一个对象叫codes1
 codes["49"] = "日本";
 console.log(codes["49"])  //我们发现复制后,另一个对象值变了,复制的对象也变了,如果我们想留一个原本的复制对象怎么办?
 //原因:因为复制的时候 栈里面复制的时候把其堆 里面的地址也复制过去了
 let a10={}
 let b10={}
 //问?
 console.log(a10===b10) //结果为false 因为他们的堆中 的位置不一样的
 //但是
 console.log(codes1===codes) //结果为true,因为复制后他们指向的是同一个堆

 //如果复制后不想影响原始的值怎么办? 用for in 循环,可以实现但太麻烦
 let codes2 = {}; //先 定义一个空对象,这个对象在堆里面有自己的地址
 for (const key in codes) {
     codes2[key] = codes[key] //在把对象复制过来
 }
 console.log(codes2["21"]);
 codes2["21"] = "澳大利亚";
 console.log(codes2["21"]) //复制的已经被修改,他更改的是他自己堆里面的
 console.log(codes["21"])  //我们发现原本的并没有被修改 这种方法可以实现,但是太麻烦 
 //复制方法2:用 object.assign()
Object.assign(codes2,codes) //克隆了codes到codes2上,堆地址也不一样  assign是分配的意思
 codes2["21"] = "澳大利亚";
 console.log(codes2["21"]) //复制的已经被修改
 console.log(codes["21"]) 

 //Object.assign扩展用法
 let user2={name:"admin"};
 //假设后台有两种权限要复制到user2上
 let jurisdiction1 = {canView:true}
 let jurisdiction2 = {canEdit:true} 
 let u2={name:"root"}
 Object.assign(user2,jurisdiction1,jurisdiction2,u2)  //把要被复制的对象写在前面,要赋予它值的对象写在后面,可以多个,如果有相同属性会被覆盖掉
 console.log(user2) //{name: 'root', canView: true, canEdit: true}

  //Object.assign扩展用法2
  let user4={};
  let user3={
      name:"xiaomi",
      sizes:{
          height:182,
          width:80,
      }
    };
Object.assign(user4,user3) //user4复制user3
user4.sizes.width=90; //user4的sizes对象下的width变了,那么user3变不变?
console.log(user3.sizes.width)  //值也是90,我们发现值也变了,因为对象里的对象存的只是堆的地址值,复制过去的只是地址,地址一样,所以object.assign复制过去要改都改了,和上面同样的道理
//所以assign是浅拷贝,如果有对象会影响原始数据,那么怎么深拷贝呢?  方法1: 递归 才能解决这个问题
function nihao(obj){
    let clone3 ={};
    for (const key in obj) {
       if(typeof obj[key] === "object"){
           clone3[key]=nihao(obj[key]); // 要复制的对象值=函数对象的值,在克隆一份出来
       }else{
        clone3[key]=obj[key]
       }
       
    }
    return clone3;
}
let user5 = nihao(user3);
user5.sizes.width=100;
console.log(user3.sizes.width) //这次我们发现值没有变,还是上面的90
//解决方法2:用JSON.stringify   这种效率高,简化版,但是不能转换null 和 undefined ,如果数据里没有这两可以用这种方法,上面那种方面用的也多
let str = JSON.stringify(user3)  //会把对象user4变成文本型的数据  和web通信常用
let obj2 = JSON.parse(str)  //再把文本转换成对象,这样就重新定义了原对象,不包含原地址信息
console.log(obj2.sizes === user3.sizes)  //结果false,已经和原对象完全不一样了



// 垃圾回收 回收所有的函数 变量,在堆上,占内存,内存的管理非常重要,闭包内存泄漏经常用

let user6={
    name:"Jone"
}
// let user6=null; //js引擎会发现当前对象已经会空,之前给他的堆地址也已经为空,没有任何一个对象可以指向它

let admin6=user6;
user6=null; //那么不会被回收,因为admin6还连着

//垃圾回收期扩展  

function marry(man,woman){
    woman.husband = man;
    man.wife= woman;
    return {
        father:man,
        mother:woman,
    }
}
let family = marry(
    {
        name:"阿杰"
    },
    {
        name:"S娃"
    }
)
family.mother.husband=null; //因为有关联关系.另一个不能被删除,想要删除必须要两句话
delete family.mother.husband
delete family.father  //写2个删除才能被删除,连接他的线都要被删了
family = null //如果全局变量被删除,那么阿杰和s娃会被回收,虽然他们俩还有关系,但是已经是孤岛了,变量没了


html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
   <script>
       //回调函数 callback  
  /*      function ask(question,yes,no){
           if(confirm(question)){
               yes()
           }else{
               no()
           }
       }
       function showOk(){
        alert("太好啦") 
       }
       function showCancel(){
        alert("那下次吧")
       }
       ask("老乡,要不要一起学习",showOk,showCancel) */

       //也可以用匿名函数写成这样的写法 ,函数可以作为参数传递到另一个函数中
       function ask(question,yes,no){
           if(confirm(question)){
               yes()
           }else{
               no()
           }
       }
      
       ask("老乡,要不要一起学习",function(){alert("太好了")},function(){alert("那下次吧!")}) //也可以写为ask("老乡,要不要一起学习",()=>alert("太好了"),()=>alert("那下次吧!")) 
   </script> 
</body>
</html>


小米技术社区