【JavaScript必知】數據類型

僅爲學習筆記

JavaScript 中的數據類型

  • 基本類型(6): nullundefinedbooleannumberstringsymbol(es6)。
  • 對象類型(1):Object

區別:

  • 基本類型存儲的都是值,對象類型存儲的是指針(內存地址)
var a = 1;   分配一塊內存#001,存放值爲1,a存放值1
var b = a;   分配一塊內存#002,存放值爲1,b存放值1
console.log(a);   1
console.log(b);   1
兩個值互不影響

var a = [];    分配一塊內存#001,存放值爲[], a存放地址#001
var b = a;     將地址#001賦值給b,此時b的地址也是#001,a和b表明同一個地址
a.push(1)
console.log(a);   [1]
console.log(b);   [1]

同一個地址表明同一個地方,因此會互相影響

複製代碼
  • 對象做爲函數參數時,參數是按值傳遞的,對象傳遞的是地址,因此存在引用。
function test(person) {
  person.age = 26 // 這裏參數傳入的是對象的地址
  person = {    // 這裏從新賦值了,至關於從新分配了地址
    name: 'yyy',
    age: 30
  }
  return person
}
const p1 = {
  name: 'yck',
  age: 25
}
const p2 = test(p1)
console.log(p1) // -> {name: 'yck', age: 25 }
console.log(p2) // -> {name: 'yyy', age: 30 }
複製代碼

檢測數據類型 typeof

typeof 對於基本類型,除了 null 均可以顯示正確的類型,對於對象沒法區分是哪種es6

typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof b // b 沒有聲明,可是還會顯示 undefined
複製代碼
typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'
複製代碼

對於 null 來講,雖然它是基本類型,可是會顯示 object算法

typeof null // 'object'
複製代碼

使用 instanceof區分對象

instanceof是經過原型鏈來判斷json

const Person = function() {}
const p1 = new Person()
p1 instanceof Person // true

var str = 'hello world'
str instanceof String // false

var str1 = new String('hello world')
str1 instanceof String // true

複製代碼

Number 類型:

JS不存在整型,所有按照 IEEE 754 雙精度版本(64位)來表示數字 而計算機計算是採用二進制,因此會將十進制先轉成2進制計算後再轉成十進制,所以計算有時會出現偏差,好比:0.2 + 0.1 = 0.30000000000000004數組

NaN 非數值的類型, 不等於本身 ,自己是一個Number類型

console.log(NaN == NAN);//false
console.log(typeof NaN); //'number'
複製代碼

isNaN():接受任意參數,試圖轉換爲數值,不能被轉換的返回true.

console.log( isNaN(NaN) ); //true
console.log( isNaN(10) ); //false
console.log( isNaN(true) ); //false
複製代碼

類型轉換

在 JS 中類型轉換隻有三種狀況,分別是:bash

  • 轉換爲Boolean
  • 轉換爲數字
  • 轉換爲字符串

轉Boolean

在條件判斷時,undefined, null, false, NaN, '', 0, -0,轉爲 false,其餘全部值都轉爲 true。閉包

對象轉原始類型

對象在轉換類型的時候,會調用內置的 [[ToPrimitive]] 函數,對於該函數來講,算法邏輯通常來講以下:app

若是已是原始類型了,那就不須要轉換了函數

  • 調用 x.valueOf(),若是轉換爲基礎類型,就返回轉換的值
  • 調用 x.toString(),若是轉換爲基礎類型,就返回轉換的值 若是都沒有返回原始類型,就會報錯 固然你也能夠重寫 Symbol.toPrimitive ,該方法在轉原始類型時調用優先級最高。
let a = {
  valueOf() {
    return 0
  },
  toString() {
    return '1'
  },
  [Symbol.toPrimitive]() {
    return 2
  }
}
1 + a // => 3

複製代碼

轉換成數值:Number,parseInt, parseFloat

Number():字符串--整數 (能夠用於任何類型總體轉換)
Number(true)--1
Number(false)-0
Number(null)--0
Number([ ])---0  
Number(' ')---0
Number([ 12])---12
Number('100')--100
Number('01000')---1000
轉不了的就返回NaN
Number('hello world')----NaN
Number(undefined)----NaN
Number([ 1,2,3])---NaN
Number(json)---NaN  json轉不了
Number(function(){} ...window等)---NaN
不能轉換含有非數字的東西:Number(100px)--NaN
因爲Number()函數在轉換字符串比較複雜且不夠合理,所以處理整數通常用parseInt()
複製代碼

parseInt() parseFloat (只針對字符串) parseInt(一個一個的轉換,若是第一個不是數字就轉成NaN,只能轉字符串類型,) parseInt(字符串,幾進制(默認10進制))學習

parseInt(100px)---100
parseInt(10px23)--10
parseInt(+100px)--100(忽略+,-,空格,0000)
parseInt(0100)---100
parseInt(12.2元)--12
parseInt('')--NaN
parseFloat(只認識第1個小數點)
parseFloat(12.32元)--12.32
parseFloat(12.3.2元)--12.3
if(parseInt(num)==parseFloat(num))  說明num是整數
複製代碼

四則運算符

加法運算符

  • 其中一方爲字符串,那麼就會把另外一方也轉換爲字符串
  • 若是一方不是字符串或者數字,那麼會將它轉換爲數字或者字符串
1 + '1' // '11'
true + true // 2
4 + [1,2,3] // "41,2,3"
複製代碼

另外對於加法還須要注意這個表達式 'a' + + 'b'ui

'a' + + 'b' // -> "aNaN"
複製代碼

由於 + 'b' 等於 NaN,因此結果爲 "aNaN",你可能也會在一些代碼中看到過 + '1' 的形式來快速獲取 number 類型。

那麼對於除了加法的運算符來講,只要其中一方是數字,那麼另外一方就會被轉爲數字

4 * '3' // 12
4 * [] // 0
4 * [1, 2] // NaN

複製代碼

比較運算符

若是是對象,就經過 toPrimitive 轉換對象 若是是字符串,就經過 unicode 字符索引來比較

let a = {
  valueOf() {
    return 0
  },
  toString() {
    return '1'
  }
}
a > -1 // true

複製代碼

在以上代碼中,由於 a 是對象,因此會經過 valueOf 轉換爲原始類型再比較值。

內置對象 Object Array Boolean Number String Funtion RegExp Error Math

Array

push():在末尾添加1項,並返回新數組的長度
pop(); 從末尾刪除1項,並返回刪除的那一項
shift(); 從前面刪除1項,並返回刪除的那一項
unshift(); 從前面增長1項,並返回新數組的長度
複製代碼

排序

  • reverse():翻轉數組項的順序
  • sort():調用數組的toString()方法,把每一個數組轉成字符串,而後兩兩想減,負數順序不變,正數交換位置,實現了從小到大排序,升序排序。由於是比較的字符串,因此沒法獲得排好順序的整數。若是要實現整數排序,能夠另外寫一個函數,利用返回值。
function compare(v1,v2){
  return v2-v1;
}
var value = [1,3,4,0,2];
value.sort(compare)
複製代碼

操做

  • join() 數組--字符串
  • concat():它會複製當前數組並把傳入的參數加在後面,生成一個新的數組。不會改變原數組。
  • slice():返回一個數組,兩個參數:起始和結束位置,不包括結束項。沒有結束項,就到最後,不改變數組自己。
  • [].slice.call(arguments)==Array.slice.call(arguments),目的是將arguments對象的數組提出來轉化爲數組,arguments自己並非數組不能調用slice() ,因此能夠經過call轉成數組
  • splice():會改變數組 兩個參數,splice(要刪除的第一項的位置,要刪除的個數) 3個參數:起始位置,要刪除的個數,要插入的項(能夠多個),會從設置的起始位置開始插入
  • indexOf()(從前日後找)和lastIndexOf()(從末尾開始找)查找,找到返回位置,沒找到返回-1. 參數:(要查找的項,查找的起始位置。(可選) )
var num = [1,2,3,4,5];
num.indexOf(4); //3
num.lastIndexOf(4); //1
複製代碼

迭代方法:參數:(運行的函數,做用域(可選))

  • every():對數組的每一項運行給定的函數,若每一項都返回ture,則最終返回true
  • filter():對數組的每一項運行給定的函數,,則最終返回true的項的數組。
  • forEach():對數組的每一項運行給定的函數,無返回值;
  • map():對數組的每一項運行給定的函數,以數組的形式返回全部項的返回值。
  • some():對數組的每一項運行給定的函數,如有一項都返回ture,則最終返回true.

縮小方法:

  • reduce():從前到後遍歷
  • reduceRight():與上面相反 參數:前一個值,當前值,索引,數組 上一次運行的返回值,會做爲第一個參數傳進去,也就是前一個值
var num = [1,2,3,4,5];
var result = num.reduce (function(prev,cur,index,array){return prev+cur;} );  返回的是每項執行結果
alert(result);//15
複製代碼

String

length:長度
var str = 'hello ';
console.log(str.charAt(0)); // h  返回單個字符
console.log(str.charCodeAt(1));  //101  返回字符編碼
console.log(str[0]);   //h  可直接經過下標
console.log(str.concat('liujingyi'));//hello liujingyi
console.log(str.concat('liu',' jing'));//hello liu jing
console.log(str+'ljy'); //hello ljy
複製代碼
var str = 'abjcdefj';
console.log(str.slice(2));      //jcdefj' 開始位置,結束位置 第二個參數默認到最後 console.log(str.substring(2)); //jcdefj'  開始位置,結束位置   第二個參數默認到最後
console.log(str.substr(2));     //jcdefj' 開始位置,返回的字符個數 第二個參數默認到最後 console.log(str.slice(2,5)); //jcd console.log(str.substring(2,5));//jcd console.log(str.substr(2,5)); //jcdef 複製代碼
  • indexOf()(從前日後找)和lastIndexOf()(從末尾開始找)查找,找到返回位置,沒找到返回-1. 參數:(要查找的項,查找的起始位置。(可選) )
  • trim():刪除先後空格
  • toUpperCase() :轉成大寫
  • toLowerCase() :轉成小寫
  • toLocaleUpperCase():針對特定地區,轉大寫、
  • toLocaleLowerCase():同上,轉小寫
  • match():參數1個:字符串或者正則, match()方法就是用來檢索一個字符串是否存在。若是存在的話,返回要檢索的字符串;若是不存在的話,返回null 。
var text = "cat,bat,sat,fat";
var result1 = text.match('at');
var result2 = text.match(/at/);
console.log(result1); //["at", index: 1, input: "cat,bat,sat,fat"]
console.log(result2); //["at", index: 1, input: "cat,bat,sat,fat"]
複製代碼
  • search():參數1個:字符串或者正則,用於檢索字符串中指定的子字符串,返回的是子字符串的起始位置,若是沒有找到任何匹配的子串,則返回-1。
var text = "cat,bat,sat,fat";
var result1 = text.search('at');
var result2 = text.search(/at/);
alert(result1); //1
alert(result2); //1
複製代碼
  • replace():參數2個:1 正則或字符串(被替換的) 2 函數或字符串(替換後的) 若是第一個參數是字符串,那麼只有字符串的第一個子字符串會被替換,想要所有替換,第一個參數用正則
var text = "cat,bat,sat,fat";
var result = text.replace("at","ond");
alert(result); //"cond,bat,sat,fat"
var text = "cat,bat,sat,fat";
var result = text.replace(/at/g,"ond");
alert(result); //"cond,bond,sond,fond"
複製代碼
  • split():分割字符串,以數組形式返回。參數2個:1 分割符,字符串或正則 2 數組的大小
var text = "cat,red,dog";
var result1 = text.split(',');// ["cat", "red", "dog"]
var result2 = text.split(); // ["cat,red,dog"]
var result3 = text.split(',',2); //  ["cat", "red"]
複製代碼
  • localeCompare():比較字符串在字母表的順序,相等返回0,若是傳入的字符串在前面就返回1,反之返回-1.
var text = "dog";
var result1 = text.localeCompare('dog');//0
var result2 = text.localeCompare('cat'); // 1
fromCharCode():傳入編碼,返回字符串
var result1 = String.fromCharCode(104,101,108,108,111); //hello
substr 參數:截取的起始位置 和長度(若是省略截取到最後)
var str="Hello world!";
var n=str.substr(2,3)
n 輸出結果:
llo
複製代碼
  • substring() 方法返回的子串包括 開始 處的字符,但不包括 結束 處的字符。 參數:開始和結束的位置 在本例中,咱們將使用 substring() 從字符串中提取一些字符::
<script>

var str="Hello world!";
document.write(str.substring(3)+"<br>");
document.write(str.substring(3,7));

</script>
以上代碼輸出結果:
lo world!
lo w
複製代碼

Date對象

var date = new Date();
var year = date.getFullYear();
var month = end(date.getMonth()+1);
var dates = end(date.getDate());
var hours = end(date.getHours()+1);
var minutes = end(date.getMinutes()+1);
var seconds = end(date.getSeconds()+1);
var dayList=['星期日','星期一','星期三','星期四','星期五','星期六'];
var day = dayList[date.getDay()];

var time = year+':'+month+':'+dates+':'+hours+':'+minutes+':'+seconds+':'+day;
console.log(time);
function end(time){
  return time<10?'0'+time:time;
}
複製代碼
  • eval():能夠執行字符串形式的JS代碼 eval("alert(1)");等同與 alert(1);

this指向

  • 當函數做爲對象的方法被調用時,this 指向該對象
  • 當函數做爲普通函數調用,this 指向 window
  • 構造器調用,當用 new 運算符調用函數時,默認狀況下,this表明構造函數返回的對象。
  • 當函數嵌套函數時,子函數中的this會指向window對象,若是子函數是箭頭函數則不會改變this的指向。
  • call,apply能夠動態地改變傳入函數的 this

原型

  • 每一個函數都有一個 prototype 屬性,存放constructor(建立該函數的構造函數) 和 __proto__

  • 每一個對象都有__proto__ 屬性,指向了建立該對象的構造函數的原型。其實這個屬性指向了 [[prototype]],可是 [[prototype]] 是內部屬性,咱們並不能訪問到,因此使用 _proto_來訪問。

  • 對象能夠經過 __proto__來尋找上一層的屬性,__proto__ 將對象鏈接起來組成了原型鏈。

function Fun() {
}
Fun.prototype = {
   constructor: f Func(),
    __proto__: Object
}
Object.prototype = {
   constructor: f Object()
}

var a = new Func()
a.__proto__ 指向Fun.prototype
Fun.prototype.__proto__指向Object.prototype
複製代碼

new

  • 新生成了一個對象
  • 連接到原型
  • 綁定 this
  • 返回新對象
  • 在調用 new 的過程當中會發生以上四件事情,咱們也能夠試着來本身實現一個 new
function create() {
    // 建立一個空的對象
    let obj = new Object()
    // 得到構造函數
    let Con = [].shift.call(arguments)
    // 連接到原型
    obj.__proto__ = Con.prototype
    // 綁定 this,執行構造函數
    let result = Con.apply(obj, arguments)
    // 確保 new 出來的是個對象
    return typeof result === 'object' ? result : obj
}
複製代碼

閉包

一個函數嵌套另外一個函數的時候,子函數能夠訪問到外部函數的變量,此時就造成了一個閉包,外部函數的變量不會被銷燬。

閉包使用場景:

  • 一列button,點擊彈出對應索引的時候:在點擊監聽事件的外層建立當即執行函數,將索引傳進去。
  • 建立私有做用域: 將代碼放在當即執行函數中,經過返回另外一個函數暴露可訪問的參數,沒暴露的外界沒法訪問。
  • 延續局部變量的壽命
閉包可能帶來的問題:

使用閉包的同時比較容易造成循環引用,若是閉包的做用域鏈中保存着一些 DOM 節點,這時候就有可能形成內存泄露。 若是要解決循環引用帶來的內存泄露問題,咱們只須要把循環引用中的變量設爲 null便可。

相關文章
相關標籤/搜索