時間對象、引用類型

1.基礎(chǔ)類型有哪些?復(fù)雜類型有哪些?有什么特征?

  • 基礎(chǔ)數(shù)據(jù)類型:指的是簡單的數(shù)據(jù)段
  • 在JavaScript中有五種基本數(shù)據(jù)類型:undefined、null、boolean、number和string。
  • 解析:基礎(chǔ)類型是保存在棧內(nèi)存中的簡單數(shù)據(jù)段。通過變量復(fù)制基礎(chǔ)類型值的時候,會建立新的內(nèi)存并在新內(nèi)存中保存相同的值。修改新的變量值不會影響被復(fù)制的變量值。
var a ="hello"
var b = a
a = "hi"
console.log(b)//"hello"
console.log(a)//"hi"

  • 復(fù)雜類型:指的是由多個值構(gòu)成的對象,包括:對象、函數(shù)、Date對象、數(shù)組、正則等
  • 解析:復(fù)雜類型也屬于引用類型。對象作為引用類型,實際上是保存在堆內(nèi)存中。而變量中保存的是指向?qū)ο笏趦?nèi)存位置的指針。通過變量復(fù)制對象的時候,新變量的指針指在相同的內(nèi)存位置。所以通過新變量修改數(shù)值的時候,被復(fù)制的變量所指向的值也會相應(yīng)改變。
var obj1={
  name:"ff",
  age:18
}
var obj2=obj1
obj2.name = "vv"
console.log(obj2)//Object {name: "vv", age: 18}
console.log(obj1)//Object {name: "vv", age: 18}

  • 基礎(chǔ)類型和復(fù)雜類型的特征
    (1)基礎(chǔ)類型的特征是存儲在棧內(nèi)存中,按值訪問,可以操作存儲在變量中的實際的值
    (2)復(fù)雜類型的特征是存儲在堆內(nèi)存中,按指針訪問,操作復(fù)雜類型的對象時實際上是操作對象的引用(指針),而非實際的對象

  • 介紹一下JavaScript的內(nèi)存機制

JavaScript中的內(nèi)存分為棧內(nèi)存和堆內(nèi)存。
棧內(nèi)存:先進后出,寄存速度快,棧數(shù)據(jù)可共享,由系統(tǒng)自動分配,數(shù)據(jù)固定不夠靈活,空間大小有限制,超出則棧溢出。
堆內(nèi)存:順序隨意,寄存速度比棧內(nèi)存慢,由程序申請,操作簡單,儲存空間大(取決于系統(tǒng)有效虛擬內(nèi)存)
基本數(shù)據(jù)類型分為變量標識和值,均保存在棧內(nèi)存,變量標識指向其對應(yīng)的值。
引用數(shù)據(jù)類型相對較為復(fù)雜,分為值、值所在堆地址以及變量標識,其中值保存在堆內(nèi)存中,變量標識和值所在堆地址保存在棧內(nèi)存,變量標識指向其對應(yīng)的值所在堆地址

參考(必看)Js內(nèi)存機制詳解


2.如下代碼的輸出? 為什么?

var obj1 = {a:1, b:2};
var obj2 = {a:1, b:2};
console.log(obj1 == obj2);//false  因為是兩個不同的對象,跟它們的值相同沒什么關(guān)系。
console.log(obj1 = obj2);//var obj1 = {a:1,b:2} //將obj2賦值給obj1。這時obj1指向obj2內(nèi)存中對象的值。
console.log(obj1 == obj2);//true  上面那個操作讓兩者指向同一引用地址了,所以是true

3.寫一個函數(shù)getIntv,獲取從當前時間到指定日期的間隔時間

題目:
var str = getIntv("2016-01-08");
console.log(str); // 距除夕還有 20 天 15 小時 20 分 10 秒
毫秒差.png
QQ圖片20161002000936.png
function getIntv(){
  var nowTime = new Date()//目前的時間
  var perTime = new Date("2016-10-01")
  d = nowTime - perTime//console.log(d)得到兩者差的毫秒數(shù)
  
  var perDay = 24*60*60*1000
      perHour = 60*60* 1000
      perMinute = 60*1000
  
  var day = Math.floor(d/perDay)//得到今日到2016.10.01距離是0日
      hour = Math.floor((d-day*perDay)/(perHour))//先相減得到剩余小時的毫秒數(shù)
      minutes = Math.floor((d-(day*perDay+hour*perHour))/(60*1000))//總毫秒數(shù)-(足一天的天數(shù)+剩余的小時)之和的秒數(shù)
      second = Math.floor((d-(day*perDay+hour*perHour+minutes*perMinute))/1000)//總毫秒數(shù)-(足一天的天數(shù)+剩余的小時+剩余的分鐘)之和的秒數(shù)
  var result = "當前時間距離2016年10月01日:"+day+"天"+hour+"小時"+minutes+"分"+second+"秒";
  console.log(result)
}

getIntv() //當前時間距離2016年10月01日:0天16小時15分7秒

留意:js里Date計算一天按每日的早上(AM)08:00才算是過了一天


4.把數(shù)字日期改成中文日期

題目:
var str = getChsDate('2015-01-08');
console.log(str); // 二零一五年一月八日
function getChsDate(str){
    var dateMessage = {
            "0": "零",
            "1": "一",
            "2": "二",
            "3": "三",
            "4": "四",
            "5": "五",
            "6": "六",
            "7": "七",
            "8": "八",
            "9": "九",
            "10": "十",
            "11": "十一",
            "12": "十二",
            "13": "十三",
            "14": "十四",
            "15": "十五",
            "16": "十六",
            "17": "十七",
            "18": "十八",
            "19": "十九",
            "20": "二十",
            "21": "二十一",
            "22": "二十二",
            "23": "二十三",
            "24": "二十四",
            "25": "二十五",
            "26": "二十六",
            "27": "二十七",
            "28": "二十八",
            "29": "二十九",
            "30": "三十",
            "31": "三十一"
       };
    var newStr = str.split("-");//["2015","01","08"]
    var year = newStr[0];
    var month = newStr[1];
    var date = newStr[2];
    
    var yearConcat =  dateMessage[year[0]]+dateMessage[year[1]]+dateMessage[year[2]]+dateMessage[year[3]],
        monthConcat = dateMessage[Number(month)],
        dateConcat = dateMessage[Number(date)];//01和10有區(qū)別,要用到Number強制轉(zhuǎn)換
    
    var result =  yearConcat+"年"+monthConcat+"月"+dateConcat+"日"
    return result
}


console.log(getChsDate('2015-01-08'))//"二零一五年一月八日"
console.log(getChsDate('2016-10-02'))//"二零一六年十月二日" 

5.寫一個函數(shù)獲取n天前的日期

題目:
var lastWeek = getLastNDays(7); // '2016-01-08'
var lastMonth = getLastNDays(30); // '2015-12-15'
function getLastNDays(n){
  var nowTime = Date.now();  
  var setdate = n*24*60*60*1000;
  var d = new Date(nowTime - setdate);//括號是得到毫秒數(shù),d則是CMT格式的時間
  var year = d.getUTCFullYear();//UTC的API
  var month = d.getUTCMonth();
  var date = d.getUTCDate();
  if(month < 10){
    month = "0"+month;
  }
  if(date<10){
    date = "0"+date
  }
  var result = year+"-"+month+"-"+date
  return result;
  
}

var lastWeek = getLastNDays(7); 
var lastMonth = getLastNDays(30);
console.log("距離現(xiàn)在時間按一個星期前的日期:"+lastWeek);
console.log("距離現(xiàn)在時間一個月前的日期:"+lastMonth);
求距離規(guī)定時間的日期.png

6.完善如下代碼,用于獲取執(zhí)行時間如:

題目:
var Runtime = (function(){ 
      //code here ... 
      var obj = { 
            start: function(){ 
                   //code here ..., 當前時間
            }, 
            end: function(){ 
                   //code here ... 結(jié)束時間 
            },
            get: function(){ 
                   //code here ... 獲取執(zhí)行時間 
            } 
      };
      return obj;
}());
Runtime.start();
//to do something
Runtime.end();
console.log( Runtime.get() );

測試一個for循環(huán)執(zhí)行要多少毫秒,計算機性能不同秒數(shù)不一樣


一個函數(shù)循環(huán)執(zhí)行要多久.png

7.樓梯有200級,每次走1級或是2級,從底走到頂一共有多少種走法?用代碼(遞歸)實現(xiàn)

思路:
1.當走一級樓梯時,只有1種走法,
2.當走二級樓梯時,有2種走法;
3.當走三級樓梯時,要么從一級樓梯上跨2級,要么從二級樓梯上跨1級,所以,三級樓梯的走法是走一級樓梯的方法加上走二級樓梯的方法,即3種走法。
4.當走四級樓梯時,同樣的思路,要么從二級樓梯上跨2級,要么從三級樓梯上跨一級,所以,四級樓梯的走法是走二級樓梯的方法加上走三級樓梯的方法,即5種走法。
5.以此類推,n級樓梯的走法,就是走(n-2)級樓梯的方法加上走(n-1)級樓梯的方法。

function fn(n){
    if(n===1){
        return 1
    }else if(n===2){
        return 2
    }
    return fn(n-1)+fn(n-2)
}
console.log(fn(4)) //輸出5種走法

運行過程拆分
fn(4)
fn(3)+fn(2)
fn(2)+fn(1)+fn(3)

console.log(fn(200)); // 打印導(dǎo)致瀏覽器崩潰, 函數(shù)的堆棧溢出導(dǎo)致
簡單的說,堆和棧(主要是棧)是存在處理上限的,一旦需要待處理的函數(shù)
中的(局部變量,傳遞參數(shù),返回值等等)超過其上限后,計算機就罷工,瀏覽器崩潰。
所以解決這類由于遞歸出現(xiàn)的堆棧溢出的最好辦法就是即時釋放,即時用閉包法

6.寫一個json對象深拷貝的方法,json對象可以多層嵌套,值可以是字符串、數(shù)字、布爾、json對象中的任意項

var objList = {
  name:"hunger",
  age:18,
  hobby:{
    a:1,
    b:2
  }
};
//深拷貝
function deepCopy(obj){
  var newObj = {};
  for(var key in obj){
    if(typeof obj[key] === "object"){//對象內(nèi)含對象再作判斷
      newObj[key] = deepCopy(obj[key])//遞歸
    }else{
       newObj[key] = obj[key]  
    }  
  }
  return newObj
}
console.log(deepCopy(objList))
console.log(deepCopy(objList) === objList);
結(jié)果1.png
//json對象可以多層嵌套
var objList = {
    "name": "hunger",
    "age": 18,
    "sex": "man",
    "local": {
        'name': "China",
        'number': 19
    },
    "hobby":['swim','run']
};

function deepCopy(obj){
  var newObj = {};
  for(var key in obj){
    if(typeof obj[key] === "object"){
      newObj[key] = deepCopy(obj[key])//遞歸
    }else{
       newObj[key] = obj[key]  
    }  
  }
  return newObj
}
console.log(deepCopy(objList))

結(jié)果如下圖:


結(jié)果1.png

深拷貝的業(yè)務(wù)場景:就是想復(fù)制一份東西,但又不想改變原來被拷貝對象中的信息,同時不想和之前拷貝的東西有關(guān)聯(lián),那么就得用上深拷貝...另外因為淺拷貝會把引用地址給一并拷貝了,容易造成修改新配置時把坐標一并修改了,所以對象中如果還含有對象層級都建議用深拷貝


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容