對象

在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)建實例。

zimianliang.jpg

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

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