鍵值對
組成的無序
集合。建立對象兩種方法 : 方法一 : 字面量方法
html
var obj = {name: "k"};
方法二 : new Object( ) 構造函數建立
windows
var a = new Object(); a.name = "zm"; console.log( a ); // {name: "zm"}
若是 想要把大象放進冰箱。數組
1.面向過程思想的邏輯思惟是:
瀏覽器
1.打開冰箱 2.把大象放入冰箱 3.關上冰箱
解析: 面向過程思想的邏輯思惟是,咱們先作什麼,而後作什麼,最後作什麼。是分步驟一步一步往下走。性能優化
疑問:
🤔️也許有許多小夥伴以爲,面向過程很符合咱們的思惟邏輯啊。的確如此,可是面向過程的缺點是擴展性和複用性不好。若是咱們想要:把獅子放入冰箱
。app
1.打開冰箱 2.拿出大象 2.把獅子放入冰箱 3.關上冰箱
把老虎放入冰箱
。函數
1.打開冰箱 2.拿出獅子 2.把老虎放入冰箱 3.關上冰箱
2.面向對象思想的邏輯思惟是:
性能
冰箱: 打開 關上 清空 動物: 進入
1.經過調用函數建立對象。
優化
<script> //函數做用:建立一個對象,帶有name和age屬性,say方法。 function createObj( name,age ){ var o={};//建立一個新的對象 o.name=name;//爲對象添加屬性 o.age=age;//爲對象添加屬性 o.say = function(){//爲對象添加方法 console.log( "我是人" ); }; return o; } var obj = createObj("kimoo",28); console.log( obj );//{name: "kimoo", age: 28, say: ƒ} var obj2 = createObj("zm",38); console.log( obj2 );//{name: "zm", age: 38, say: ƒ} console.log(obj.say===obj2.say);//false </script>
解析: say 方法,每次調用函數都會生成一個新的對象,會生成新的say( )方法。因此,每次調用createObj( name,age ); ,都會生成新的say( )方法,可是每一個say方法的功能都同樣,這樣對性能有影響。this
2.經過調用函數建立對象,性能優化。
<script> // 批量建立對象 var obj = createObj("kimoo",28); console.log( obj ); obj.say(); var obj2 = createObj("zm",38); console.log( obj2 ); obj2.say(); console.log( obj.say === obj2.say ); // true function say(){ console.log( "我是人" ); } function createObj( name,age ){ var o = {}; o.name = name; o.age = age; o.say = say; return o; } </script>
3.函數的比較
var fn1 = function(){ alert(1); }; var fn2 = function(){ alert(1); }; console.log( fn1 === fn2 ); // false //--------------------------------------------------- var temp = function(){alert(2)}; var fn3 = temp; var fn4 = temp; console.log( fn3 === fn4 );// true
解釋:不管如何定義一個函數,JS解釋器都會把它翻譯成一個Function對象
。因此每次建立一個自定義函數,都會建立一個新的對象。例如:fn1和 fn2變量都是存儲對象的地址,雖然建立新對象的內容是同樣的,可是在瀏覽器解析的時候,它會給對象建立一個地址。fn1和fn2存儲的地址不相等,故fn1和fn2不相等。
fn3存儲是temp接受的對象的地址,fn4存儲也是temp接受的對象的地址。故fn3和fn4不相等。
狀況一:沒有返回值,打印的是undefined。
<script> function fn(){ console.log( 1 ); } var res1 = fn(); console.log( res1 );//undefined
解析:當函數沒有返回值的時候,將函數調用賦給變量,打印的值是undefined。由於沒有返回值。
狀況二:使用 new 來調用函數,沒有返回值,打印的是{}(空對象)。
使用 new 來調用函數 函數內部會自動return 一個對象 若是函數內部使用了 return X 若是 X 是一個 非null 的 對象res 那麼經過new 調用 ,返回的是 res 若是 X 是 非對象 或者 null 那麼經過new 調用 ,返回的是 {}
舉例說明:
<script> function fn(){ console.log( 1 ); // return 2;//當return的值是2,console.log( res2 )打印結果是{} // return null;//當return的值是null,console.log( res2 )打印結果是{} // return {b:3};//當return的值是{b:3},console.log( res2 )打印結果是{b:3} } var res2 = new fn(); console.log( typeof res2 );//object console.log( res2 ); </script>
進一步對狀況二說明:使用 new 來調用函數的過程
使用 new 來調用函數
第一步:函數內部會自動
爲咱們建立一個對象
第二步:函數內部的 this
指向會變爲 當前構造函數生成的對象
第三步:會自動return
。
<script> function fn(name, age){ //第一步 var obj = {}; console.log( this );//第二步:這個this指向的是生成的對象res。打印結果是:fn{} this.name = name; this.age = age; } // fn(); //若是是這樣直接調用,指向的是windows。 var res = new fn("kimoo",28); // 此處: 經過new 調用fn , // fn 被稱爲 構造函數 // res 是 fn 的 實例 // 整個過程 被稱爲 實例化 console.log( res ); //fn {name: "kimoo", age: 28} </script>
約定: 構造函數的大駝峯寫法
<script> function CreatePerson( name,age ){ this.name = name; this.age = age; this.say = function(){ console.log( "我是人"); } } var p1 = new CreatePerson("kimoo",28); console.log( p1 );//{name: "kimoo", age: 28, say: ƒ} p1.say();//我是人 var p2 = new CreatePerson("zm",38); console.log( p2 );//{name: "zm", age: 38, say: ƒ} p2.say();//我是人 console.log( p1.say === p2.say ); //false 性能上的浪費:方法並無共享。爲解決這個問題,除了上面把函數提取出來的方法,可使用prototype。 </script>
prototype (原型):當一個函數被申明的時候,該函數下默認有一個屬性:prototype,該屬性的值是一個對象。
<script> function CreatePreson(){} console.dir( CreatePreson ); </script>
結果爲:
當咱們去調用一個對象的屬性或者方法的時候,
若是該對象自身沒有該屬性或方法
,則會調用到該對象 的 構造函數的prototype的屬性或方法
。
把經過構造函數構造出來的對象,共有的方法或者屬性,放在prototype身上,可以達到性能節約的辦法。
<script> function CreatePreson(){ } CreatePreson.prototype.say = function(){console.log(1);}; CreatePreson.prototype.name = "k"; var p = new CreatePreson(); p.say();// 當咱們去調用一個對象的屬性或者方法的時候,自身沒有的時候,找構造函數的prototype的屬性或者方法 console.log( p.name ); // 當咱們去調用一個對象的屬性或者方法的時候,自身沒有的時候,找構造函數的prototype的屬性或者方法 var p2 = new CreatePreson(); p2.say();// 當咱們去調用一個對象的屬性或者方法的時候,自身沒有的時候,找構造函數的prototype的屬性或者方法 console.log( p2.name ); // 當咱們去調用一個對象的屬性或者方法的時候,自身沒有的時候,找構造函數的prototype的屬性或者方法 console.log( p.say === p2.say );//true </script>
__proto__ 當一個對象被建立的時候,該對象會自動被添加上一個屬性:__proto__,他的值也是一個對象,而且該屬性 就是 當前這個對象的構造函數的prototype 對象.__proto__ === 構造函數.prototype
<script> function CreatePreson(){}; var p1 = new CreatePreson(); console.log( CreatePreson.prototype === p1.__proto__ );//true
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="box"></div> <script> function CraetTab(param) { this.el = param.el; this.buttonText = param.buttonText;//button按鈕的內容 this.contentText = param.contentText;//div的內容 this.button = [];//生成button元素用button數組存儲 this.content = [];//生成div元素用div數組存儲 this.current = 0;//記錄當前顯示的button和div this.autoPlay = param.autoPlay!==undefined?param.autoPlay:true;//默認自動播放 } CraetTab.prototype.init=function () { //生成對應style樣式 var style=document.createElement("style"); style.innerHTML="#"+this.el.id+" .active{background-color: red;}#"+this.el.id+" .show{display: block;}#"+this.el.id+" div{display: none;}"; document.body.appendChild(style); //根據建立對象的buttonText個數生成button //並把每個生成的button塞入數組中 //將生成的button添加到box中 for(var i=0;i<this.buttonText.length;i++){ var btu=document.createElement("button"); btu.innerHTML=this.buttonText[i]; this.button.push(btu); this.el.appendChild(btu); } //根據建立對象的contentText個數生成div //並把每個生成的div塞入數組中 //將生成的div添加到box中 for(var i=0;i<this.contentText.length;i++){//生成div var div=document.createElement("div"); div.innerHTML=this.contentText[i]; this.content.push(div); this.el.appendChild(div); } //若是this.autoPlay爲真,則開啓定時器,讓選項卡自動播放 if(this.autoPlay){ var num=0; var that=this;//因爲在setInterval事件中this就指的是當前的window。因此要在外部存儲指向對象的this。 setInterval(function () { for(var i=0;i<that.buttonText.length;i++){ that.button[i].classList.remove("active"); that.content[i].classList.remove("show"); } that.button[num].classList.add("active"); that.content[num].classList.add("show"); num++; num%=that.buttonText.length; },1000) } this.setCss(); this.addEvent(); }; //大清洗,給當前顯示的div和button添加樣式 CraetTab.prototype.setCss=function () { for(var i=0;i<this.buttonText.length;i++){ this.button[i].classList.remove("active"); this.content[i].classList.remove("show"); } this.button[this.current].classList.add("active"); this.content[this.current].classList.add("show"); }; //給button添加點擊事件,點擊哪一個就將that.current的值改爲對應button的索引值。 CraetTab.prototype.addEvent=function () { var that=this;//因爲在button點擊事件中this就指的是當前的button。因此要在外部存儲指向對象的this。 for(var i=0;i<this.buttonText.length;i++){ this.button[i].index=i; this.button[i].onclick=function () { that.current= this.index; that.setCss(); } } }; var box=document.getElementById("box"); var t1 =new CraetTab({ el: box, buttonText: [ "按鈕1", "按鈕2", "按鈕3" ], contentText:[ "內容1", "內容2", "內容3" ], autoPlay:false }); t1.init(); </script> </body> </html>