JavaScript變量類型

數據類型

對外的,面對編譯器segmentfault

基本數據類型(值類型)

包括數組

  • Undefined
  • Null
  • Boolean
  • String
  • Number 
  • Symbol(ES6)

存放位置:內存中的棧區域。
值的不可變性,稱這些類型的值爲原始值。
基本數據類型的值是按值訪問的,基本類型的值是不可變的。
比較:基本數據類型的比較是值的比較,只判斷是否相等。
拷貝:都是值的複製,相互沒有影響。數據結構

引用數據類型(對象類型)

包括函數

  • Object
  • Array
  • Function
  • RegExp
  • Date

存放位置:內存中的棧存放指向堆區域的指針,內容在堆區域中
值的可變性:引用類型的值是按引用訪問的,引用類型的值是動態可變的
比較: 引用類型的比較是引用地址的比較,判斷是否指向同一對象。
拷貝:spa

  • 賦值:僅改變引用的指針,指向同一個對象,相互影響
  • 淺拷貝:拷貝一層,不對對象的子對象進行拷貝,對第一層的基本類型的修改互不影響,對於子對象會相互影響。
  • 深拷貝:對對象中的子對象進行遞歸拷貝,拷貝先後的兩個對象互不影響。

undefined 和 null 的區別?

undefined:是一個沒有設置值的變量。JavaScript特有的。沒有返回值的函數返回爲undefined,沒有實參的形參也是undefined。
null:它是一個空對象指針。
null 和 undefined 的值相等,但類型不等:prototype

typeof undefined             // undefined
typeof null                  // object
null === undefined           // false
null == undefined            // true

基本數據類型和引用類型的數據結構

基本數據類型:數據存於內存中的棧區域。
應用數據類型:內存中的棧存放指向堆區域的指針,內容在堆區域中。
搜狗截圖20200306191015.png
搜狗截圖20200306191927.png指針

賦值、淺拷貝和深拷貝

若是是基本數據類型,直接賦值,會拷貝其自己,不存在淺拷貝和深拷貝。
若是是引用類型:code

  • 賦值:僅改變引用的指針,指向同一個對象,相互影響
  • 淺拷貝:拷貝一層,不對對象的子對象進行拷貝,對第一層的基本類型的修改互不影響,對於子對象會相互影響。
  • 深拷貝:對對象中的子對象進行遞歸拷貝,拷貝先後的兩個對象互不影響。
賦值
let obj1 = {
    color: 'red',
    age: 20,
    address: {
        city: 'beijing',
    },
    arr: ['a', 'b', 'c']
};
//賦值
let obj2 = obj1;
obj1.age = 21;
obj1.address.city = "shanghai";
console.log(obj2.age);//21
console.log(obj2.address.city);//shanghai
淺拷貝
let obj1 = {
    color: 'red',
    age: 20,
    address: {
        city: 'beijing',
    },
    arr: ['a', 'b', 'c']
};
//淺拷貝
let obj3 = shallowCopy(obj1);
obj1.age = 21;
obj1.address.city = "shanghai";
console.log(obj3.age); //20
console.log(obj3.address.city); //shanghai

//自定義淺拷貝函數
function shallowCopy(obj) {
    if (typeof obj !== 'object' || obj == null) {
        return obj;
    }
    let result;
    if (obj instanceof Array) {
        result = [];
    } else {
        result = {};
    }
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            result[key] = obj[key];
        }
    }
    return result;
}
深拷貝
let obj1 = {
    color: 'red',
    age: 20,
    address: {
        city: 'beijing',
    },
    arr: ['a', 'b', 'c']
};
//深拷貝
let obj4 = deepCopy(obj1);
obj1.age = 21;
obj1.address.city = "shanghai";
console.log(obj4.age);//20
console.log(obj4.address.city);//shanghai

//自定義深拷貝函數
function deepCopy(obj) {
    // obj 是 null 或者不是對象和數組,直接返回
    if (typeof obj !== 'object' || obj == null) {
        return obj;
    }
    // 初始化返回結果
    let result;
    if (obj instanceof Array) {
        result = [];
    } else {
        result = {};
    }
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            result[key] = deepCopy(obj[key]);
        }
    }
    return result;
}

本地對象

對內的,供開發者使用
  • 包裝類型對象對象

    • Boolean
    • String
    • Number
  • 引用類型blog

    • Array
    • Function
    • Date
    • Object
    • RegExp
    • Error
  • 內置對象
    在腳本程序初始化時被建立,沒必要實例化這兩個對象。

    • Global
    • Math

基本包裝類型

在實際中每讀取一個基本數據值的時候,後臺就會建立一個對應的基本包裝類型對象,從而讓咱們可以調用一些方法操做這些數據。

let s1 = "some text"; //值類型沒有方法。
let s2 = s1.substring(2);
console.log(s1); //some text
console.log(s2); //me text

引用類型與基本包裝類型的區別
它們的對象生命週期不一樣:
引用類型:使用new建立引用類型的實例,在執行數據流離開當前做用域時會一直存儲在內存中。
基本包裝類型:自動建立基本包裝類型的對象,只執行一行代碼的瞬間以後就會當即銷燬。
這意味着在運行時爲基本包裝類型值添加屬性和方法是無效的。

let s1 = 'some text';
s1.color = 'red';
s1.color // undefined

// 可是這樣是能夠的
let s1 = new String('some text');
s1.color = 'red';
s1.color // red

不建議顯式的建立基本包裝類型的對象,由於在不少時候會形成一些讓人很迷惑的東西。

let b = new Boolean(false); //b 這個變量就是 Boolean 對象
let c = b && true;
console.log(c); // true
let str = 'hello'; // str 本質上是一個原始值,並不存在 prototype 屬性
console.log(typeof str); // string
console.log(str instanceof String); // false

參考文章:https://segmentfault.com/a/11...

類型判斷

typeof

相較於JS基本數據類型少null多function。
console.log(typeof null); //object
console.log(typeof undefined); //undefined
console.log(typeof 123); //number
console.log(typeof "123"); //string
console.log(typeof true); //boolean
console.log(typeof function a() {}); //function
console.log(typeof [1, 2, 3]); //object
console.log(typeof {a: "a"}); //object

instanceof

  • 肯定原型指向關係。只適用於對象,由於值類型沒有原型。
  • 不能判斷一個對象實例具體屬於哪一種類型。
let a = [];
console.log(a instanceof Array);//true
console.log(a instanceof Object);//true

Object.prototype.toString.call()

  • Object 的原型方法,返回"[object type]",其中type是對象的類型。
  • toString()調用null返回[object, Null],undefined返回[object Undefined]。
  • 沒法識別自定義的對象類型。
console.log(Object.prototype.toString.call(123)); //[object Number]
function optc(obj) {
    return Object.prototype.toString.call(obj).slice(8, -1);
}

console.log(optc(123)); //Number
console.log(optc('123')); //String
console.log(optc(true)); //Boolean
console.log(optc(undefined)); //Undefined
console.log(optc(null)); //Null
console.log(optc({})); //Object
console.log(optc([])); //Array
console.log(optc(function () {})); //Function
console.log(optc(/\d/)); //RegExp
console.log(optc(new Date())); //Date

constructor(構造函數)

利用構造函數判斷數據類型。

  • 對象的構造函數名就是該數據類型。
  • 除Null和Undefined外,全部的數據類型都是/能夠轉化爲對象,而若是是對象,就確定有構造函數。
function A() {}

let a = new A();
console.log(a.constructor.toString()); //function A() {}

總結

準確判斷數據類型包括自定義的對象類型
function dataType(data) {
    if (!data) { //判斷null、undefined
        return Object.prototype.toString.call(data).slice(8, -1);
    } else {
        return data.constructor.toString().match(/function\s*([^(]*)/)[1];
    }
}
console.log(dataType(null)); //null
console.log(dataType(undefined)); //Undefined
console.log(dataType(123)); //Number
console.log(dataType([])); //Array

function Point(x, y) {}
console.log(dataType(new Point(1, 2))); //Point

類型轉換

強制類型轉換

1. 轉換成字符串

String()

此方法經常使用於null和undefined轉換成字符串類型

toString()

此方法不適合用於null和undefined
對象 返回值
Number 返回當前數值的字符串
String 字符串自己
Boolean false-->"false"
Array [1,2,3]-->"1,2,3"
Function 返回當前函數源代碼的字符串
Object "[object object]"
Date 返回表示UTC的字符串
Symbol "Symbol()"

2. 轉換成數字

Number()

Number方法只要字符串中有一個字母則返回NaN,而且能夠轉換boolear類型。Number()能夠用於任何數據類型。

parseInt()和parseFloat()

parseInt方法在字符串中遇到數值轉換成數字,若是遇到非數字就會返回,不能轉換boolear類型。parseInt()和parseFloat()則專門用於字符串。
let str1 = "123";
let str2 = "abc";
let str3 = "123abc";
let a = true;
console.log(Number(str1)); // 123
console.log(Number(str2)); // NaN
console.log(Number(str3)); //NaN
console.log(Number(a)); //1
console.log(parseInt(str1)); // 123
console.log(parseInt(str2)); //NaN
console.log(parseInt(str3)); //123
console.log(parseInt(a)); //NaN

3. 轉換成布爾類型

Boolean()
五種轉換爲false的狀況:null,undefined,''(空字符串),0,NaN。其他爲true。

隱式類型轉換

1. 四則運算符帶來的類型轉換

轉換規則
加法運算:
一方是字符串,另外一方也會被轉換爲字符串類型。加法運算會觸發3種類型轉換

  • 將值轉換爲原始值
  • 將值轉換爲數字
  • 將值轉化爲字符串

其餘運算:雙方會被轉爲數字進行運算。

console.log(1 + "1"); //1
console.log(1 * "2"); //2
console.log([1, 2] + [3, 4]); //1,23,4
console.log('a' + +'b'); //aNaN
/* 轉換步驟
* +'b' -> 'NaN'
* 'a' + 'NaN' -> 'aNaN'
*/

2. "=="

  • == 會發生類型轉換,使兩邊儘可能相等。
類型(x) 類型(y) 結果
null undefined true
number string 把y轉化爲number,再與x進行比較
boolean 任何類型 把x轉換爲number,再與x進行比較
string或number object 把y轉換爲原始值,再與x進行比較
object object 若是它們指向同一個對象,則返回true;不然返回false
  • 使用==的狀況:除了==null以外,其餘一概都用 ===
const obj = {x: 100};
if (obj.a == null) {}
//至關於:
//if (obj.a === null || obj.a === undefined) {}
  1. if 語句和邏輯運算

if 語句中就是判斷 truly 變量和 falsely 變量。

//如下是falsely 變量。除此以外都是 truly 變量
console.log(!!0 === false);
console.log(!!NaN === false);
console.log(!!null === false);
console.log(!!undefined === false);
console.log(!!false === false);

邏輯判斷(隱式轉換成Boolean值)

console.log((10 && 0)); //0
console.log(("" || "abc")); //abc
console.log((!global.abc)); //true
相關文章
相關標籤/搜索