在js中有一句話叫:“萬物皆對象”
JavaScript 中的所有事物都是對象:字符串String、數(shù)值Number、數(shù)組Array、函數(shù)Function...
一、對象的定義:
對象是JavaScript的一個基本數(shù)據(jù)類型,是一種復合值,它將很多值(原始值或者其他對象)聚合在一起,可通過名字訪問這些值。即屬性的無序集合。
對象只是帶有屬性和方法的特殊數(shù)據(jù)類型 ,并且有一個原型對象。原型要么是一個對象,要么是null值。
二、對象的創(chuàng)建
-
通過Object對象創(chuàng)建
person=new Object(); person.firstname="John"; person.lastname="Doe"; person.age=50; person.eyecolor="blue"; -
使用構(gòu)造器創(chuàng)建對象
function person(firstname,lastname,age,eyecolor) { this.firstname=firstname; this.lastname=lastname; this.age=age; this.eyecolor=eyecolor; }
-
使用對象字面量創(chuàng)建對象
person={firstname:"John",lastname:"Doe",age:50,eyecolor:"blue"};區(qū)別:
經(jīng)過個人總結(jié),對象字面量就是不用js的new操作符創(chuàng)建實例。

1.對象字面量比new Object() 更高效;{}是字面量,可以立即求值,而new Object()本質(zhì)上是方法(只不過這個方法是內(nèi)置的)調(diào)用,既然是方法調(diào)用,就涉及到在proto鏈中遍歷該方法,當找到該方法后,又會生產(chǎn)方法調(diào)用必須的堆棧信息,方法調(diào)用結(jié)束后,還要釋放該堆棧;
2.萬萬沒想到
console.time("start{}");
for(let i =0;i<=1000;i++){
let a={
b:1,
c:2
}
}
console.timeEnd("start{}");
console.time("start new");
for(let i =0;i<=1000;i++){
let a=new Object();
a.b=1;
a.c=2;
}
console.timeEnd("start new");
//輸出:start{}: 0.098876953125ms
// start new: 0.173095703125ms
三、對象的分類:
-
普通對象Object
除開函數(shù)對象之外的對象都是普通對象
var foo = {
x: 10,
y: 20
};
- 函數(shù)對象Function Object
什么是函數(shù)對象?
函數(shù)對象就是函數(shù)。函數(shù)對象對應的類型是Function。
? 怎么創(chuàng)建函數(shù)對象?
1.通過Function構(gòu)造函數(shù)進行創(chuàng)建
var fname = new Function("test", "alert(''+test);");
第一個參數(shù)實際上是表示要傳入函數(shù)中的參數(shù),二第二個參數(shù)表示的是當前的函數(shù)要執(zhí)行的過程。
兩個參數(shù)實際上都是string類型的。在上面的形式中,每個 arg 都是一個參數(shù),最后一個參數(shù)是函數(shù)主體(要執(zhí)行的代碼);但是又上可以看出實際上當前的內(nèi)容是十分的繁雜。用這種方法,執(zhí)行效率方面會打折扣,且似乎無法傳遞參數(shù),所以少用為妙。
2.通過關鍵字function創(chuàng)建具名函數(shù)
function fname(test){ alert(""+test); }
這種創(chuàng)建方式也叫作函數(shù)聲明
3.通過關鍵字function創(chuàng)建匿名函數(shù)
var fname = function(test){alert(""+test);}
這種創(chuàng)建方式也叫作函數(shù)表達式
? 函數(shù)表達式和函數(shù)聲明
函數(shù)聲明:
function 函數(shù)名稱 (參數(shù):可選){ 函數(shù)體 }
函數(shù)表達式:
function 函數(shù)名稱(可選)(參數(shù):可選){ 函數(shù)體 }
ECMA規(guī)范只明確了一點:函數(shù)聲明必須帶有標示符(Identifier)(就是大家常說的函數(shù)名稱),而函數(shù)表達 式則可以省略這個標示符
function foo(){} // 聲明,因為它是程序的一部分
var bar = function foo(){}; // 表達式,因為它是賦值表達式的一部分
new function bar(){}; // 表達式,因為它是new表達式
(function(){
function bar(){} // 聲明,因為它是函數(shù)體的一部分
})();
所以,可以看出,如果不聲明函數(shù)名稱,它肯定是表達式,可如果聲明了函數(shù)名稱的話,如何判斷是函數(shù)聲明還是函數(shù)表達式呢?ECMAScript是通過上下文來區(qū)分的,如果function foo(){}是作為賦值表達式的一部分的話,那它就是一個函數(shù)表達式,如果function foo(){}被包含在一個函數(shù)體內(nèi),或者位于程序的最頂部的話,那它就是一個函數(shù)聲明。
? 區(qū)別
函數(shù)聲明會在任何表達式被解析和求值之前先被解析和求值(聲明的作用域提升,講作用域的時候詳細解說),即使你的聲明在代碼的最后一行,它也會在同作用域內(nèi)第一個表達式之前被解析/求值,函數(shù)聲明在JS解析時進行函數(shù)提升,因此在同一個作用域內(nèi),不管函數(shù)聲明在哪里定義,該函數(shù)都可以進行調(diào)用。而函數(shù)表達式的值是在JS運行時確定,并且在表達式賦值完成后,該函數(shù)才能調(diào)用。參考如下例子:
1 funDeclaration("Declaration");//=> true
2 function funDeclaration(type){
3 return type==="Declaration";
4 }
1 funExpression("Expression");//=>error
2 var funExpression = function(type){
3 return type==="Expression";
4 }
函數(shù)聲明的實際規(guī)則如下:
函數(shù)聲明只能出現(xiàn)在程序或函數(shù)體內(nèi)。從句法上講,它們 不能出現(xiàn)在Block(塊)({ ... })中,例如不能出現(xiàn)在 if、while 或 for 語句中。因為 Block(塊) 中只能包含Statement語句, 而不能包含函數(shù)聲明這樣的源元素。另一方面,仔細看一看規(guī)則也會發(fā)現(xiàn),唯一可能讓表達式出現(xiàn)在Block(塊)中情形,就是讓它作為表達式語句的一部分。但是,規(guī)范明確規(guī)定了表達式語句不能以關鍵字function開頭。而這實際上就是說,函數(shù)表達式同樣也不能出現(xiàn)在Statement語句或Block(塊)中(因為Block(塊)就是由Statement語句構(gòu)成的)。
注:切忌不要在if 、else 、for 、while 等邏輯控制等語句中創(chuàng)建函數(shù)聲明或者函數(shù)表達式
使用Function創(chuàng)建函數(shù)的注意點
從技術角度講,這是一個函數(shù)表達式。一般不推薦用這種方法定義函數(shù),因為這種語法會導致解析兩次代碼(第一次是解析常規(guī)ECMAScript代碼,第二次是解析傳入構(gòu)造函數(shù)中的字符串),從而影響性能。
var name='bianbumei';
function fun(){
var name='zhaoyongfu';
return new Function('return name');//不能獲取局部變量
}
console.log(fun()());//bianbumei
Function()構(gòu)造函數(shù)每次執(zhí)行時都會解析函數(shù)主體,并創(chuàng)建一個新的函數(shù)對象,所以當在一個循環(huán)或頻繁執(zhí)行的函數(shù)中調(diào)用Function()構(gòu)造函數(shù)效率是非常低的。而函數(shù)表達式卻不是每次遇到都會重新編譯的,用Function()構(gòu)造函數(shù)創(chuàng)建一個函數(shù)時并不遵循典型的作用域,它一直把它當作是頂級函數(shù)來執(zhí)行。
自調(diào)用函數(shù)
函數(shù)表達式可以 "自調(diào)用"。
自調(diào)用表達式會自動調(diào)用。
如果表達式后面緊跟 () ,則會自動調(diào)用。
不能自調(diào)用聲明的函數(shù)。
通過添加括號,來說明它是一個函數(shù)表達式:
(function () {
var x = "Hello!!"; // 我將調(diào)用自己
})();
//這個方式其實可以轉(zhuǎn)化成這樣子
let fun=function () {
var x = "Hello!!"; // 我將調(diào)用自己
};
fun();