JavaScript面向?qū)ο缶幊讨改?-讀書筆記(上)

第一章:面向?qū)ο蟮腏avaScript

面向?qū)ο蟮某绦蛟O計

面向?qū)ο蟪绦蛟O計(oop)中最常用到的概念:

  • 對象、方法、屬性
  • 封裝
  • 聚合
  • 重用與繼承
  • 多態(tài)

封裝通常有兩部分組成。

  • 相關(guān)的數(shù)據(jù)(用于存儲數(shù)據(jù))
  • 基于這些數(shù)據(jù)所能做的事情(多能調(diào)用的方法)

通過繼承可以實現(xiàn)代碼的復用。

第二章:基本數(shù)據(jù)類型、數(shù)組、循環(huán)及條件表達式

基本數(shù)據(jù)類型

  • 數(shù)字 ——包括浮點數(shù)與整數(shù),列如這些屬于數(shù)字,1、100、3.14;
  • 字符竄 ——包括由任意數(shù)量字符組成的序列,例如:“a”、“one”、“one 2 three”;
  • 布爾值 ——包括true和false;
  • undefined ——不存在的變量,或者聲明未初始化的變量,值只有一個:undefined;
  • null ——通常指沒有或者是空值。

JavaScript數(shù)據(jù)類型主要分為兩個部分:

  • 基本數(shù)據(jù)類型;
  • 非基本類型(即對象)

任何不屬于基本數(shù)據(jù)類型的東西都屬于對象。
可以使用查看類型操作符——typeof 查看某個變量或者值的類型是什么。

數(shù)組

數(shù)組是一種數(shù)據(jù)存儲的形式,數(shù)組的聲明:
var a=[];
var a=[1,2,3];
數(shù)組的索引下標是從0開始的,并且按照每一個元素的位置依次遞增
可通過方括號中的索引值訪問數(shù)組元素,可存儲任何類型的數(shù)據(jù),包括另一個數(shù)組。

條件與循環(huán)表達式

  • if條件表達式
  • switch語句
  • while、do-while、for,及for-in循環(huán)

第三章:函數(shù)

什么是函數(shù)

function sum(a, b) {
    var c=a+b;
    return c;
} 

一般來說,函數(shù)聲明通常是由下面幾部分組成的:
1.關(guān)鍵詞function;
2.函數(shù)名稱,這里即sum;
3.函數(shù)需要的參數(shù);
4.函數(shù)所要執(zhí)行的代碼塊,稱為函數(shù)體;
5.return 子句。函數(shù)通常有返回值,且只有一個,如要返回多個,可以可考慮放進一個數(shù)組。

arguments:函數(shù)內(nèi)建變量,接收的所有參數(shù),結(jié)構(gòu)類似數(shù)組,可通過索引進行運用。

預定義函數(shù)

  • parseInt(); // 接收任何輸入值轉(zhuǎn)換為整數(shù)型輸出 ,記得定義第二個參數(shù)確定輸出的是什么進制的數(shù)值,默認是十進制,例如,從日歷中讀日期,對于08這樣的數(shù)值,如果不定義,會出現(xiàn)意想不到的結(jié)果。
  • paseFlat( ); // 功能和parseInt( )差不多,它只支持將輸入值轉(zhuǎn)為十進制,因此該函數(shù)只有一個參數(shù);可接受指數(shù)形式的數(shù)據(jù),這一點和parseInt()不同。
  • isNaN( );
  • isFinite( );
  • encodeURI( );
  • decodeURI( );
  • ...

函數(shù)的作用域

沒有塊作用域,只有函數(shù)作用域,“全局變量”指的是所有函數(shù)外的變量,與之對應的“局部變量”是指在某個函數(shù)中定義的變量。函數(shù)內(nèi)的代碼可以訪問全局變量,反之不行。

  var a=3;
  function text(){
    alert(a);
    var a=5;
    alert(a);
  }
text();

上面的例子,第一個alert 結(jié)果是undefined,第二個則為5;

函數(shù)也是數(shù)據(jù)

在JavaScript中,函數(shù)也是數(shù)據(jù),也就是說我們可以把函數(shù)賦值給一個變量,

  var f=function(){
      return 1;
  }

上面的這種定義方式也稱為函數(shù)標識法。
function(){return 1} 是一種函數(shù)表達式,其可以被命名,稱為命名函數(shù)表達式,所以以下是合法的,

 var f = function myFunc(){
    return 1;
  }

函數(shù)聲明和函數(shù)命名函數(shù)表達式的差別表現(xiàn)在于他們的上下文,函數(shù)聲明只出現(xiàn)在程序代碼里(在另一個函數(shù)體中,或者在主程序中)

匿名函數(shù)和回調(diào)函數(shù)

  var f=function(a){
    return a;  
  }

匿名函數(shù)即沒有名字的函數(shù),特別是它不被賦值給變量,單獨使用的時候,通過匿名函數(shù)可以做些什么呢:

  • 可將匿名函數(shù)作為參數(shù)傳給其他函數(shù),,這樣,接收函數(shù)就能利用我們傳遞的函數(shù)來完成某些事
  • 可以定義某些匿名函數(shù)進行某些一次性的任務
 function byTwo(a,b,c,callback){
  var arr=[];
  for(var i=0;i<3;i++){
    arr[i]=callback(arguments[i]*2);
  }
  return arr;
}
byTwo(1,2,3,function(a){ return a+1 }) //  輸出 [3,5,7]

以上例子為匿名函數(shù)在回調(diào)函數(shù)中的用處,

(function(){
    alert('box');
})()

匿名函數(shù)在即時(自調(diào))函數(shù)中作用,其最大的好處是不會產(chǎn)生任何的全局變量,其無法重復執(zhí)行,所以適合執(zhí)行一些一次性的或初始化的任務。

閉包

討論閉包需要了解作用域的概念,
我們知道,JavaScript不存在大括號級的作用域,但它有函數(shù)作用域,也就是說函數(shù)內(nèi)定義的所有變量在該函數(shù)外是不可見的,而在函數(shù)內(nèi)可以訪問的變量既來自它自身的作用域,可以來自其“父級”作用域,這樣就形成了一條作用域鏈,該鏈的長度(深度)取決于我們的需要。

閉包#1

var a="global variable";
var F=function(){
  var b="local variable";
  var N=function(){
    var c="inner local"
    return b;
  };
return N;
}
console.log(b)  //  undefined
var inner= F();
inner(); // local variable

函數(shù)F中包含局部變量b,因此后者在全局空間里是看不到的,N有自己的私有空間,但同時可以訪問F()的空間和全局空間,所以b對于來它是可見得。因為F()是可以在全局空間被調(diào)用的,所以我們將它的返回值賦于另一個全局變量,從而生成可以訪問F()私有空間的全局函數(shù)。

閉包#2

function F(){
  var arr=[],
  for(var i=0;i<3;i++){
    arr[i]=function(){
      return i;
    }
  }
  return arr;
}
F() // 輸出 [3,3,3];
function F(){
  var arr=[],
  for(var i=0;i<3;i++){
    arr[i]=(function(x){
      return x;
    })(i)
  }
  return arr;
}
F() // 輸出 [3,3,3];

第四章:對象

這一章主要講的是:

  • 如何創(chuàng)建并使用對象;
  • 什么是構(gòu)造器對象;
  • JavaScript中的內(nèi)置對象及運用;

事實上對象和數(shù)組的情況很相似,不同的是鍵值類型是自定義的,索引方式不再是數(shù)字,而是一些更友好的鍵名。

 var hero={
  breed: 'Turtle',
  occupation: 'Ninja'
}

正如所見:

  • 一個用于表示該對象名的hero;
  • 與定義數(shù)組時所用的中括號[ ]不同的是使用{ };
  • 中括號分割開的是組成該對象的元素(通常稱為屬性);
  • 鍵/值之間使用冒號隔開

對象的屬性可以有函數(shù),稱之方法,

 var hero={
  breed: 'Turtle',
  occupation: 'Ninja',
  getbreed: function(){
        return this.breed;
    }
}
// 可通過兩種方式訪問對象的屬性
hero.breed; // 方式一
hero['breed']; // 方式二
// 調(diào)用對象的方法和其他函數(shù)的方式相同,在指定的函數(shù)名后面加一對括號即可:
hero.getbreed() ; 
hero['getbreed']();

構(gòu)造器函數(shù)

我們可以通過構(gòu)造器函數(shù)的方式來創(chuàng)建對象,

  function Hero(){
    this.occupation='Ninja';
  }

  var hero=new Hero();
  hero.occupation   // 'Ninja'

使用構(gòu)造器創(chuàng)建對象,可以進行傳參,可以利用同一個構(gòu)造器創(chuàng)建不同的對象。
構(gòu)造器屬性
當創(chuàng)建對象時,同時也賦予該 對象一個特殊的屬性---即構(gòu)造函數(shù)屬性(constructor property) ,該屬性實際上是一個指向用于創(chuàng)建該對象的構(gòu)造器函數(shù)的引用。

hero.constructor //   "function Hero(){  this.occupation='Ninja';}"
typeof(hero.constructor) // "function"

instanceof操作符
通過instanceof操作符可以測試一個對象是不是由某個構(gòu)造器函數(shù)所創(chuàng)建的。

hero.instanceof.Hero // true

返回對象的函數(shù)
不使用new操作符調(diào)用構(gòu)造函數(shù)創(chuàng)建對象以外,拋開new操作符,只用一般的函數(shù)來創(chuàng)建對象。

function factory(name){
    return {
        name:name
    }
}
var o = faactory('jay');
o.name // 'jay'

傳遞對象和比較對象
對象的拷貝和傳遞,都是對象的引用,在引用上所做的任何改動,實際上都會影響它所引用的原對象。

var a = { num: 1 };
var b = a;
b.num; // 1
b.num = 2;
a.num; // 2
var a = { num: 1 };
var b = { num: 1 };
a === b; // fasle
a == b; // fasle
var c = a; 
c === a; // true

內(nèi)建對象

  • Object
  • Array
  • Function
  • Boolean
  • Number

第五章:原型

本章涉及的話題

  • 介紹每個函數(shù)都擁有的prototype屬性,而該屬性所存儲的就是原型對象
  • 如何為原型對象添加屬性
  • 如何使用原型對象中的新增屬性
  • proto介紹,該屬性用于保存各對象原型的神秘鏈接
  • 原型方法介紹,包括isProtottypeOf()、hasOwnProprety()、propertyIsEnumerable()等
 function foo(a,b){
  return a*b;
}
foo.length; // 2
foo.constructor; // function foo(a,b){ return a*b; }
typeof foo.prototype; // object
foo.prototype={ }; //  可以向添加屬性和方法,對 foo不會有影響,當foo為構(gòu)造函數(shù)時,其才會起作用

對于原型來說,最重要的一點是理解它的‘實時性’,在JavaScript中,幾乎所有的對象都是靠傳遞引用的方式來進行傳遞的,所以我們所創(chuàng)建的每一個對象實例并沒有屬于自己的原型副本,可隨時修改prototype屬性,由同一構(gòu)造器所創(chuàng)建的所有對象的prototype屬性也會一起改變。

自身屬性和原型屬性
當我們訪問對象實例的某個屬性時,JavaScript會遍歷所有該對象所有屬性,如果找到該屬性后立即返回,如果沒有找到,腳本引擎會繼續(xù)去查詢用于創(chuàng)建當前對象的構(gòu)造器的原型。如果在原型中找到該實例會立即使用該屬性。

function Hero(){
 this.name = 'java';
this.sex = 'man'
}
Hero.prototype.info='it';
Hero.prototype.sex ='woman';
var hero = new Hero();
hero.name ; // 'java'
hero.info ; // 'it'
hero.sex; // 'man'
hero.hasOwnProperty('sex') //  true;
hero.hasOwnProperty('info') //  false;

當自身屬性和原型屬性同名時,自身的屬性優(yōu)先級高于原型屬性,使用
hasOwnProperty方法可以判斷一個對象的屬性時自身屬性還是原型屬性。

枚舉屬性
for適合使用在數(shù)組上,for-in更適合對象,如果想獲得某個對象的所有屬性的類列表,可以使用for-in。

 var params={
  productid: 666,
  section: 'products'
}
var url = 'https://example.org/page.php?',
      i,
      quert = [];

for( i in params){
  quert.push(i + '=' + params[i]);
}
url += quert.join('&') // url = 'https://example.org/page.php?productid=666&section=products',

需要注意的細節(jié):

  • 并不是所有的屬性 for- in 循環(huán)都可以顯示的,例如(數(shù)組) length、construction 屬性就不會被顯示,那些會顯示的屬性稱為可枚舉的,可通過propertyIsEnumerable方法來判斷對象的某個屬性是否可枚舉。
  • 原型鏈中的各個原型屬性也會被顯示出來,當然前提是他們是可枚舉的。
  • 對于所有的原型屬性, propertyIsEnumerable 都會返回false
function Fadget(name,color){
  this.name = name;
  this.color = color;
  this.getName = function(){
    return this.name;
  }
}
Fadget.prototype.price = 10;
Fadget.prototype.rating = 3;

var newtoy = new Fadget('webcam','black');
for( var prop in newtoy){
  console.log(prop + '=' + newtoy[prop ])
}
// name = name
// name = name
// getName = function(){
    return this.name;
  }
// price  = 10
// rating = 3

// 使用hasOwnProperty對對象屬性和原型屬性做一個區(qū)分
newtoy .hasOwnProperty('name '); // true
newtoy .hasOwnProperty('price '); // false

for(var porp in newtoy ){
  if(newtoy.hasOwnProperty(porp)) {
    console.log(porp + '=' +newtoy[porp] );
  }
}
// name = name
// name = name
// getName = function(){
    return this.name;
  }

//propertyIsEnumerable,該方法會對所有的非內(nèi)建對象屬性返回true
//而對于內(nèi)建對象和方法來說,大部分都是不可枚舉的,
newtoy.propertyIsEnumerable('name ')  // true
newtoy.propertyIsEnumerable('constructor ')  // false

//任何原型鏈上的屬性也是不可枚舉的
newtoy.propertyIsEnumerable('price ')  // false

// 但需要注意,如果propertyIsEnumerable()調(diào)用的是來自原型鏈上的某個對象,那么該對象中的屬性也是枚舉的
newtoy.constructor .prototype.propertyIsEnumerable('price ')  // true

每個對象中都有isPrototypeOf()方法,這個方法會告訴我們當前對象是否是另一個對象的原型。
proto IE 之類平臺不存在,所以使用上存在不能夸平臺,還有和prototype 并不等價的,它屬于某個對象實例的屬性,而后者是屬于構(gòu)造函數(shù)的。

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

相關(guān)閱讀更多精彩內(nèi)容

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