avaScript中的數(shù)據(jù)類型檢測(cè)是一個(gè)重要的概念,它涉及到如何確定一個(gè)變量或者值的類型。在JavaScript中,有多種方法可以用來檢測(cè)數(shù)據(jù)類型,包括typeof、instanceof、Object.prototype.toString、Array.isArray和NaN判斷等。下面將詳細(xì)介紹這些數(shù)據(jù)類型檢測(cè)方案:
綜上所述,JavaScript提供了多種數(shù)據(jù)類型檢測(cè)方案,每種方案都有其用途和限制。在實(shí)際開發(fā)中,應(yīng)根據(jù)具體需求選擇合適的方法來確保數(shù)據(jù)類型的正確判斷。
JavaScript中,有多種方法可以判斷一個(gè)變量的數(shù)據(jù)類型。以下是一些常見的方法:
typeof 是JavaScript中的一元操作符,返回一個(gè)表示未計(jì)算變量類型或已計(jì)算對(duì)象類型的字符串。但是,需要注意的是 typeof 對(duì)于 null 和 array 的處理可能不是你所期望的:
console.log(typeof undefined); // "undefined"
console.log(typeof 123); // "number"
console.log(typeof 'hello'); // "string"
console.log(typeof true); // "boolean"
console.log(typeof {}); // "object"
console.log(typeof []); // "object" 而不是 "array"
console.log(typeof null); // "object" 而不是 "null"
console.log(typeof function(){}); // "function"
instanceof 操作符用于檢測(cè)構(gòu)造函數(shù)的 prototype 屬性是否出現(xiàn)在對(duì)象的原型鏈中的任何位置。這主要用于檢測(cè)對(duì)象是否屬于某個(gè)類。
console.log([] instanceof Array); // true
console.log(null instanceof Object); // false,因?yàn)?null 不是一個(gè)對(duì)象
這是檢測(cè)一個(gè)值是否為數(shù)組的最佳方法。
console.log(Array.isArray([])); // true
console.log(Array.isArray({})); // false
這個(gè)方法返回表示該對(duì)象的字符串。對(duì)于檢測(cè)原始值類型,特別是當(dāng) typeof 給出不直觀的結(jié)果時(shí)(如 null 和 array),這是一個(gè)很有用的方法。
function getType(obj) {
return Object.prototype.toString.call(obj).slice(8, -1);
}
console.log(getType(null)); // "Null"
console.log(getType([])); // "Array"
console.log(getType({})); // "Object"
console.log(getType(123)); // "Number"
console.log(getType('hello')); // "String"
console.log(getType(true)); // "Boolean"
console.log(getType(undefined)); // "Undefined"
每個(gè)JavaScript對(duì)象都有一個(gè) constructor 屬性,它指向創(chuàng)建該對(duì)象的構(gòu)造函數(shù)。但請(qǐng)注意,如果 constructor 被手動(dòng)修改,則可能不準(zhǔn)確。
console.log(([]).constructor===Array); // true
console.log(({}).constructor===Object); // true
某些內(nèi)置對(duì)象(如 Array、Date、RegExp 等)的 @@toStringTag 屬性值是一個(gè)字符串,該字符串用于定制 Object.prototype.toString.call(obj) 的默認(rèn)行為。但通常你不需要直接使用這個(gè)屬性,除非你在實(shí)現(xiàn)自定義對(duì)象并希望改變 Object.prototype.toString.call(obj) 的默認(rèn)行為。
在 javascript 中,判斷一個(gè)變量的類型可以用 typeof
在 javascript 中,instanceof 用于判斷某個(gè)對(duì)象是否被另一個(gè)函數(shù)構(gòu)造使用 typeof 運(yùn)算符時(shí)采用引用類型存儲(chǔ)值會(huì)出現(xiàn)一個(gè)問題,無論引用的是什么類型的對(duì)象,它都返回”object”。ECMAScript 引入了另一個(gè) Java 運(yùn)算符 instanceof 來解決這個(gè)問題。
Instanceof 運(yùn)算符與 typeof 運(yùn)算符相似,用于識(shí)別正在處理的對(duì)象的類型。與 typeof 方法不同的是,instanceof 方法要求開發(fā)者明確地確認(rèn)對(duì)象為某特定類型
typeof 只能區(qū)分值類型
typeof undefined // undefined
typeof null // object
typeof console.log // function
typeof NaN // number
軟件模塊之間總是存在著一定的接口,從調(diào)用方式上,可以把他們分為三類:同步調(diào)用 、回調(diào) 和 異步調(diào)用
同步調(diào)用 是一種阻塞式調(diào)用,調(diào)用方要等待對(duì)方執(zhí)行完畢才 返回,它是一種單向調(diào)用;
回調(diào) 是一種雙向調(diào)用模式,也就是說,被調(diào)用方在接口被調(diào)用時(shí)也會(huì)調(diào)用對(duì)方的接口;
異步調(diào)用 是一種類似消息或事件的機(jī)制,不過它的 調(diào)用方向剛好相反,接口的服務(wù)在收到某種訊息或發(fā)生某種事件時(shí),會(huì)主動(dòng)通知客戶方(即調(diào)用客戶方的接口)。回調(diào)和異步調(diào)用的關(guān)系非常緊密,通常我們使用回 調(diào)來實(shí)現(xiàn)異步消息的注冊(cè),通過異步調(diào)用來實(shí)現(xiàn)消息的通知。同步調(diào)用是三者當(dāng)中最簡(jiǎn)單的,而回調(diào)又常常是異步調(diào)用的基礎(chǔ),因此,下面我們著重討論回調(diào)機(jī)制在不同軟件架構(gòu)中的實(shí)現(xiàn)
回調(diào)函數(shù) 就是一個(gè)通過函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用來調(diào)用其所指向的函數(shù)時(shí),我們就說這是回調(diào)函數(shù)。回調(diào)函數(shù)不是由該函數(shù)的實(shí)現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時(shí)由另外的一方調(diào)用的,用于對(duì)該事件或條件進(jìn)行響應(yīng)
案例:
#include<stdio.h>
//callbackTest.c
//1.定義函數(shù) onHeight(回調(diào)函數(shù))
//@onHeight 函數(shù)名
//@height 參數(shù)
//@contex 上下文
void onHeight(double height, void *contex)
{
printf("current height is %lf", height);
}
//2.定義 onHeight 函數(shù)的原型
//@CallbackFun 指向函數(shù)的指針類型
//@height 回調(diào)參數(shù),當(dāng)有多個(gè)參數(shù)時(shí),可以定義一個(gè)結(jié)構(gòu)體
//@contex 回調(diào)上下文,在 C 中一般傳入 nullptr,在 C++中可傳入對(duì)象指針
typedef void (*CallbackFun)(double height, void *contex);
//定義全局指針變量
CallbackFun m_pCallback;
//定義注冊(cè)回調(diào)函數(shù)
void registHeightCallback(CallbackFun callback, void *contex)
{
m_pCallback=callback;
}
//定義調(diào)用函數(shù)
void printHeightFun(double height)
{
m_pCallback(height, NULL);
}
//main 函數(shù)
int main()
{
//注冊(cè)回調(diào)函數(shù) onHeight
registHeightCallback(onHeight, NULL);
//打印 height
double h=99;
printHeightFun(99);
}
“閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。例如在 javascript 中,只有函數(shù)內(nèi)部的子函數(shù)才能讀取局部變量,所以閉包可以理解成“定義在一個(gè)函數(shù)內(nèi)部的函數(shù)“。在本質(zhì)上,閉包是將函數(shù)內(nèi)部和函數(shù)外部連接起來的橋梁。”
舉例:創(chuàng)建閉包最常見方式,就是在一個(gè)函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù)。下面例子中的 closure 就是一個(gè)閉包
function func(){
var a=1 ,b=2;
funciton closure(){
return a + b;
}
return closure;
}
內(nèi)存泄漏指任何對(duì)象在您不再擁有或需要它之后仍然存在
function foo(arg) {
bar='some text'; // 等同于 window.bar='some text';
}
function foo() {
this.var1='potential accident'
}
在 JavaScript 中使用 setInterval 非常常見
大多數(shù)庫都會(huì)提供觀察者或者其它工具來處理回調(diào)函數(shù),在他們自己的實(shí)例變?yōu)椴豢蛇_(dá)時(shí),會(huì)讓回調(diào)函數(shù)也變?yōu)椴豢蛇_(dá)的。對(duì)于 setInterval,下面這樣的代碼是非常常見的:
var serverData=loadData();
setInterval(function() {
var renderer=document.getElementById('renderer');
if(renderer) {
renderer.innerHTML=JSON.stringify(serverData);
}
}, 5000); //This will be executed every ~5 seconds.
這個(gè)例子闡述著timers 可能發(fā)生的情況:計(jì)時(shí)器會(huì)引用不再需要的節(jié)點(diǎn)或數(shù)據(jù)
JavaScript 開發(fā)的一個(gè)關(guān)鍵方面就是閉包:一個(gè)可以訪問外部(封閉)函數(shù)變量的內(nèi)部函數(shù)。由于 JavaScript 運(yùn)行時(shí)的實(shí)現(xiàn)細(xì)節(jié),可以通過以下方式泄漏內(nèi)存:
var theThing=null;
var replaceThing=function () {
var originalThing=theThing;
var unused=function () {
if (originalThing) // a reference to 'originalThing'
console.log("hi");
};
theThing={
longStr: new Array(1000000).join('*'),
someMethod: function () {
console.log("message");
}
};
};
setInterval(replaceThing, 1000);
有時(shí)候,在數(shù)據(jù)結(jié)構(gòu)中存儲(chǔ) DOM 結(jié)構(gòu)是有用的。假設(shè)要快速更新表中的幾行內(nèi)容。將每行DOM 的引用存儲(chǔ)在字典或數(shù)組中可能是有意義的。當(dāng)這種情況發(fā)生時(shí),就會(huì)保留同一 DOM 元素的兩份引用:一個(gè)在 DOM 樹種,另一個(gè)在字典中。如果將來某個(gè)時(shí)候你決定要?jiǎng)h除這些行,則需要讓兩個(gè)引用都不可達(dá)。
var elements={
button: document.getElementById('button'),
image: document.getElementById('image')
};
function doStuff() {
elements.image.src='http://example.com/image_name.png';
}
function removeImage() {
// The image is a direct child of the body element.
document.body.removeChild(document.getElementById('image'));
// At this point, we still have a reference to #button in the
//global elements object. In other words, the button element is
//still in memory and cannot be collected by the GC.
}
JavaScript 是一種通過原型實(shí)現(xiàn)繼承的語言與別的高級(jí)語言是有區(qū)別的,像 java,C#是通過類型決定繼承關(guān)系的,JavaScript 是的動(dòng)態(tài)的弱類型語言,總之可以認(rèn)為 JavaScript 中所有都是對(duì)象,在 JavaScript 中,原型也是一個(gè)對(duì)象,通過原型可以實(shí)現(xiàn)對(duì)象的屬性繼承,JavaScript 的對(duì)象中都包含了一個(gè)” prototype”內(nèi)部屬性,這個(gè)屬性所對(duì)應(yīng)的就是該對(duì)象的原型
“prototype”作為對(duì)象的內(nèi)部屬性,是不能被直接訪問的。所以為了方便查看一個(gè)對(duì)象的原型,Firefox 和 Chrome 內(nèi)核的 JavaScript 引擎中提供了”proto“這個(gè)非標(biāo)準(zhǔn)的訪問器(ECMA 新標(biāo)準(zhǔn)中引入了標(biāo)準(zhǔn)對(duì)象原型訪問器”Object.getPrototype(object)”)
原型的主要作用就是為了實(shí)現(xiàn)繼承與擴(kuò)展對(duì)象
JavaScript 原型: 每個(gè)對(duì)象都會(huì)在其內(nèi)部初始化一個(gè)屬性,就是 prototype(原型)
原型鏈:當(dāng)我們?cè)L問一個(gè)對(duì)象的屬性時(shí),如果這個(gè)對(duì)象內(nèi)部不存在這個(gè)屬性,那么他就會(huì)去 prototype 里找這個(gè)屬性,這個(gè) prototype 又會(huì)有自己的 prototype,于是就這樣一直找 下去,也就是我們平時(shí)所說的原型鏈的概念
特點(diǎn):JavaScript 對(duì)象是通過引用來傳遞的,我們創(chuàng)建的每個(gè)新對(duì)象實(shí)體中并沒有一份屬于自己的原型副本。當(dāng)我們修改原型時(shí),與之相關(guān)的對(duì)象也會(huì)繼承這一改變
繼承有以下六種方法:
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。