對象(名詞):是指「事物」在程序設計語言中的表現形式。
這裏的事物能夠是任何東西,咱們能夠看到它們具備某些明確特徵,能執行某些動做。
這些對象特徵就叫作屬性(形容詞),動做稱之爲方法(動詞)。javascript
類:實際上就是對象的設計藍圖或製做配方。類更多的是一種模板,而對象就是在這些模版的基礎上被建立出來的。html
封裝:主要闡述對象中包含的內容。一般包括:java
聚合:將幾個現有對象合併成一個新對象的過程
繼承:實現代碼重用
多態:不一樣對象經過相同的方法調用來實現各自行爲的能力
web
2e+3表示在數字2後面加3個0,即2000ajax
typeof Infinity // number typeof NaN // number typeof null // object null值表示一個空指針對象
Javascript引擎在一個邏輯表達式中遇到一個非布爾類型操做數,
那麼該操做數的值就會成爲該表達式返回的結果。正則表達式
true || "something" //true true && "something" //"something"
var s = "1s"; //隱式轉換Number()用於任何數據類型 s++ //NaN 10 % "0" //NaN 若是被除數是有限大的數值而除數是零,則結果是NaN //乘法口訣程序代碼 for(var i=1;i<10;i++){ for(var j=1;j<=i;j++){ document.write(j+"*"+i+"="+i*j+" "); } document.write("<br>"); }
函數內部都有一個內建的arguments數組,能返回函數所接收的全部參數編程
function sumOnSteroids(){ var i,res = 0; for(i = 0; i < arguments.length; i++){ res += arguments[i]; } return res; } sumOnSteroids(1,2,3,4,5,6); //21
var a = 123; function f(){ alert(a); //undefined 這是由於函數域優先於全局域 var a = 1; alert(a); //1 } f();
當咱們將函數B傳遞給函數A,並由A來執行B時,B就成了一個回調函數json
function A(a,b,c,callback){ var i=0,ar = []; for(i=0;i<3;i++){ ar[i] = callback(arguments[i]*2); } return ar; } function B(a){ //回調函數 return a+1; } A(a,b,c,B)
(function(name){ alert('Hello '+name+' !'); })('Jesse') //Hello Jesse ! //第二對括號起到的是當即調用的做用,同時也是向函數傳遞參數的地方
使用自調函數的好處是不會產生任何全局變量,缺點是沒法重複執行,這使得匿名自調函數最合適於執行一些一次性的或者初始化的任務設計模式
function a(param){ function b(theinput){ //私有函數 return theinput * 2 }; return 'The result is '+b(param) }
使用私有函數的好處:數組
這對於要執行某些一次性初始化工做的函數很是有用
function a(){ alert('A'); //第一次調用該函數時該語句會被執行 a = function(){ //第一次調用時a被賦予新函數 alert('B'); //第二次調用該函數時該語句會被執行 }; } var a = function(){ function someSetup(){ var setup = 'done' } function actualWork(){ alert('work') } someSetup(); return actualWork; }();
在函數內定義的變量在函數外是不可見的,
可是若是該變量是在某個代碼塊中定義的(if或for語句中),它在代碼塊外是可見的。
在javascript中每一個函數都有一個屬於本身的詞法做用域,也就是說每一個函數
在被定義時(而非執行時)都會建立一個屬於本身的環境(即做用域)
function f1(){var a = 1;f2();} function f2(){return a;} //f2()被定義時a是不可見的,只能訪問自身做用域和全局做用域 f1(); //a is not defined
function f(){ var b = "m"; return function(){ //有着私有做用域,能夠訪問f()的做用域和全局做用域 return b; } } var n = f(); n(); //m
f()是全局函數,咱們能夠將它的返回值賦值給另外一個全局變量,
從而生成一個能夠訪問f()私有空間的新全局函數
若是一個函數在其父函數返回以後想留住對父級做用域的連接,就必需要爲此創建一個閉包
function f(){ var a = []; for(var i = 0; i < 3; i++){ a[i] = function(){ return i; } } return a; } var s = f(); s[0](); //3 s[1](); //3 s[2](); //3
咱們在這裏建立了3個閉包,它們都指向一個共同的局部變量i,
可是閉包不會記錄它們的值,他們所擁有的只是一個i的引用,
所以只能返回i的當前值(循環結束時i=3).
function f(){ var a = []; for(var i = 0; i < 3; i++){ a[i] = (function(x){ return function(){ return x; } })(i); } return a; } var s = f(); s[0](); //0 s[1](); //1 s[2](); //2
1.十六進制值轉爲顏色函數getRGB()
function getRGB(hex){ var rgb=[0,0,0]; if(/#(..)(..)(..)/g.test(hex)){ rgb=[parseInt(RegExp.$1,16),parseInt(RegExp.$2,16),parseInt(RegExp.$3,16)]; }; return "rgb("+rgb.join(",")+")"; } getRGB('#00ff00'); //"rgb(0,255,0)"
用[]定義數組的方法咱們稱之爲數組文本標識法
用{}定義對象的方法咱們稱之爲對象文本標識法
在javascript中咱們用數組表示索引型數組,用對象表示關聯型數組
通常經過如下兩種方式訪問對象的屬性:
function Hero(name){ //構造器函數首字母大寫 this.name = name; this.occupation = 'ninja' } var hero = new Hero('jesse'); //使用new操做符建立新對象 hero.name; //ninja
使用構造器函數的好處是能利用同一個構造器函數經過傳參從而建立出不一樣的對象。
事實上程序所在的宿主環境通常都會爲其提供一個全局對象,
而所謂的全局變量其實只不過是該對象的屬性
構造器屬性其實是一個指向用於建立該對象的構造器函數的引用
hero.contructor //Hero
經過instanceof操做符,咱們能夠測試一個對象是否是由某個指定的構造器函數所建立的
hero instanceof Hero; //true
引用類型,由於其值大小不固定,所以棧內存中存放的只是該對象的訪問地址,(即該對象的引用)
堆內存爲這個值分配空間。所以咱們在引用上所作的任何改動,都會影響到他所引用的源對象。
全部對象都繼承自Object對象,所以都具備toLocaleString()、toString()和valueOf()方法。
var o = new Object(); var o = {}; alert(o); //[object,Object]
因爲alert()要接收字符串參數,因此它會在後臺調用toString()方法
Object構造器的成員:
用Object()構造器所建對象的成員:
var a = new Array(); var a = []; typeof a; //'object' 數組也是對象
值得關注的數組的屬性與方法
Array對象的成員:
函數實際上也是一種對象,函數對象的內建構造器是Function()
定義函數的三種方式:
function sum(a,b){return a + b;}; //函數聲明
var sum = function(a,b){return a + b;}; //函數表達式
var sum = new Function('a','b','return a + b;'); //Function構造器 避免使用
function A(){return A.caller;} function B(){return A();} B(); //function B(){return A();}
Function對象繼承自Object對象,默認擁有Object對象的全部方法
call()、apply()方法都能讓對象去借用其餘對象中的方法爲己所用,這也是一種代碼重用的方式。
var someObj = { name: 'Ninja', say: function(who){ return 'Hello '+who+', my name is '+ this.name; } }; var myObj = { name:'Jesse' }; someObj.say.call(myObj, 'Dude');//"Hello Dude, my name is Jesse" //當say()被調用時其中的this就被自動設置成myObj對象的引用
若是咱們調用call方法時須要傳遞更多的參數,能夠在後面依次加入他們
someObj.say.call(myObj,'a','b','c')
若是咱們沒有將對象傳遞給call()的首參數,或者傳遞的是null,則它的調用對象默認爲全局對象
someObj.say.apply(myObj,['a','b','c'])
(function(count){ if(count < 5){ console.log(count); arguments.callee(++count); } })(1) //1,2,3,4
Function對象的成員
var b = new Boolean(); typeof b; //'object' typeof b.valueOf();// 'boolean'
Number對象的toString()方法有一個可選的radix參數(默認10)
var n =new Number(255); n.toString(16); // 'ff'
Number()構造器的成員
Number對象的成員
當咱們將一個基本字符串當作對象來使用時,後臺會執行相應的String對象建立操做
String()構造器的成員
String對象的成員
Math對象既不能當作通常函數來使用,也不能用new操做符建立對象,只是一個包含一系列方法和屬性的內建對象
獲取某個max和min之間的值,公式((max-min)*Math.random())+min
Math對象的成員
Date()構造器成員
Date對象的成員
var reg = new RegExp('j.*t'); var reg = /j.*t/; //匹配任何以j開頭t結尾的字符串,且這倆字符之間包含1個或多個字符
var reg = /j.*t/img;
/j.*t/i.test('Javascript') //true /j.*t/i.exec('Javascript')[0] //Javascript
var s = new String('HelloJavascriptWorld'); s.match(/j.*a/ig); //['Java'] s.search(/j.*a/i); //5 //當某個匹配對象被找到時,若是咱們想讓相關的替換字符串中包含匹配的文本,可使用$&修飾符 s.replace(/[A-Z]/g,'_$&'); //"_Hello_Javascript_World" //若是正則表達式分了組(即帶括號),那麼能夠用$1表明匹配分組中的第一組,$2表明第二組 s.replace(/[A-Z]/g,'_$1'); //"_Hello_Javascript_World" var csv = 'one, two,three ,four'; csv.split(/\s*,\s*/) //["one", "two", "three", "four"] // \s*匹配0個或多個空格 //以上的4個方法能夠接受的參數也包括字符串 "test".replace('t','r'); //"rest"
RegExp對象的成員
try{ //可能會致使錯誤的代碼 }catch(e){ //在發生錯誤時處理代碼 }finally{ //可選的 //不管如何都會執行的代碼 }
c = [1,2,[1,2]]; c.sort(); //[1, [1,2], 2]
四、在String()構造器不存在時,自定義MyString()構造器函數並經過如下測試
function MyString(string){ //this.length = this.toString = function(){ return string.toString(); } this.valueOf = function(){ return string.valueOf(); } this.reverse = function(){ return Array.prototype.reverse.apply(string.split('')).join(''); } } var s = new MyString('hello'); s.length; //5 s[0]; //'h' s.toString(); //'hello' s.valueOf(); //'hello' s.chatAt(1); //'e' s.concat(' world!'); //'hello world!' s.slice(0,-1); //'hell' s.split('l'); //['he','','o']
六、在Array()不存在時,建立MyArray()構造器並經過如下測試
var a = new MyArray(1,2,3,'test'); a.length;//4 a.toString();//'1,2,3,test' a[a.length - 1];//'test' a.push('boo');//5 a.pop();//'1,2,3,test' a.join(',');//'1,2,3,test' function MyArray(){ this.length = }
若是在一個對象自身屬性中沒有找到指定的屬性,就能夠去原型鏈中查找相關屬性。可是若是趕上對象自身屬性與原型鏈屬性同名時,那麼對象自身屬性的優先級高於原型鏈屬性。
function Gadget(name,color){ this.name = name; this.color = color; this.method =function(){ return 1; } } Gadget.prototype.price = 10; Gadget.prototype.rating = 3; var newtoy = new Gadget('webcam','back'); for(var prop in newtoy){ console.log(prop + '=' + newtoy[prop]); } //name=webcam //color=back //method=function (){return 1;} //price=10 //rating=3
hasOwnProperty()方法用於區分對象自身屬性(返回true)與原型屬性(返回false)
newtoy.hasOwnProperty('name'); //true newtoy.hasOwnProperty('price'); //false
propertyIsEnumerable()方法對全部非內建對象屬性返回true,表示可經過for-in枚舉;
newtoy.propertyIsEnumerable('name'); //true
isPrototypeOf()方法會告訴咱們當前對象是不是另外一個對象的原型
var monkey = { hair:true, feeds:'bananas', breathes:'air' }; function Human(name){ this.name = name; } Human.prototype = monkey; var jesse = new Human('Jesse'); monkey.isPrototypeOf(jesse); //true
爲Array對象添加inArray()方法,用於查詢數組中是否存在某個特定的值
if(!Array.prototype.inArray){ //若是想經過原型爲某個對象添加新屬性,請務必檢查該屬性是否已存在 Array.prototype.inArray = function (needle){ for(var i = 0;i < this.length; i++){ if(this[i] == needle){ return true; } } return false; } } var a = ['a','b','c']; a.inArray('d'); //false
爲String對象添加reverse()方法,用於反向輸出該字符串
if(!String.prototype.reverse){ //若是想經過原型爲某個對象添加新屬性,請務必檢查該屬性是否已存在 String.prototype.reverse = function(){ return Array.prototype.reverse.apply(this.split('')).join(''); } } "Jesse".reverse(); //"esseJ" //首先利用this.split('')將目標字符串轉爲數組,並做爲apply()的第二個參數,第一個參數不傳值時默認爲全局對象 //再調用數組的reverse()方法生成反向數組 //最後經過join()方法將數組轉化爲字符串
解決方法:當咱們重寫某對象的prototype時,必須重置相應的constructor屬性
var shape = { type:"triangle", getType:function(){ return this.type; } } function Triangle(a,b,c){ this.a = a; this.b = b; this.c = c; } Triangle.prototype = shape; //當咱們重寫某對象的prototype時,必須重置相應的constructor屬性 Triangle.prototype.constructor = Triangle; Triangle.prototype.getPerimeter = function(){ return this.a + this.b + this.c; } var t = new Triangle(1,2,3); for(var prop in t){ if(t.hasOwnProperty(prop)){ console.log(prop + '=' + t[prop]); } } t.constructor; //Trianle(a,b,c) shape.isPrototypeOf(t); //true t.getPerimeter(); //6 t.getType(); //"triangle"
function Shape(){ this.name = 'shape'; this.toString = function(){return this.name;}; } function TwoDShape(){ this.name = '2D shape'; } function Triangle(side,height){ this.name = 'Triangle'; this.side = side; this.height = height; this.getArea = function(){ return this.side*this.height/2; } } TwoDShape.prototype = new Shape(); Triangle.prototype = new TwoDShape(); //咱們用構造器Shape()另建了一個新的實體,而後用它去覆蓋該對象的原型 //這確保了在繼承實現以後,咱們對Shape()所進行的任何修改、重寫、刪除都不會對TwoShape()產生影響 TwoDShape.prototype.constructor = TwoDShape; Triangle.prototype.constructor = Triangle; var my = new Triangle(5,10); my.getArea();//25 my.toString(); // Triangle
function Shape(){}; Shape.prototype.name = 'shape'; Shape.prototype.toString = function(){return this.name;}; function TwoDShape(){}; TwoDShape.prototype = new Shape(); TwoDShape.prototype.constructor = TwoDShape; //咱們須要在對原型對象進行擴展以前,先完成相關繼承關係的構建 TwoDShape.prototype.name = '2D shape'; function Triangle(side,height){ this.side = side; this.height = height; } Triangle.prototype = new TwoDShape(); Triangle.prototype.constructor = Triangle; Triangle.prototype.name = 'Triangle'; Triangle.prototype.getArea = function(){ return this.side*this.height/2; }
function Shape(){}; Shape.prototype.name = 'shape'; Shape.prototype.toString = function(){return this.name;}; function TwoDShape(){}; //TwoDShape.prototype = new Shape(); new Shape()會將Shape的屬性設定爲對象自身屬性,這樣的代碼是不可重用的 TwoDShape.prototype = Shape.prototype; TwoDShape.prototype.constructor = TwoDShape; TwoDShape.prototype.name = '2D shape'; function Triangle(side,height){ this.side = side; this.height = height; } Triangle.prototype = TwoDShape.prototype; //這樣當然能夠提升效率,可是子對象和父對象都指向同一對象,一旦對原型屬性進行修改,繼承的對象相關屬性也隨之改變 Triangle.prototype.constructor = Triangle; Triangle.prototype.name = 'Triangle'; Triangle.prototype.getArea = function(){ return this.side*this.height/2; } var s = new Shape(); s.name;//"Triangle"
在構建繼承關係的過程當中引入一個uber屬性,並令其指向其父級原型對象
當對象類型的屬性拷貝時,實際上拷貝的只是該對象在內存中的位置指針,這一過程就是淺拷貝
//淺拷貝 function extendCopy(p){ var c = {}; for(var i in p){ c[i] = p[i]; } c.uber = p; return c; } //深拷貝 function deepCopy(p,c){ var c = c || {}; for(var i in p){ if(typeof p[i] === 'object'){ c[i] = (p[i].constructor == Array) ? [] : {}; deepCopy(p[i],c[i]); //在遇到一個對象引用型的屬性時,須要再次調用深拷貝 }else{ c[i] = p[i]; } } return c; } var parent = { numbers:[1,2,3], letters:['a','b','c'], obj:{prop:1}, bool:true }; var mydeep = deepCopy(parent); var myshallow = extendCopy(parent); mydeep.numbers.push(4,5,6); //6 mydeep.numbers; //[1, 2, 3, 4, 5, 6] parent.numbers; //[1, 2, 3] myshallow.numbers.push(10); //4 myshallow.numbers; //[1, 2, 3, 10] parent.numbers; //[1, 2, 3, 10] mydeep.numbers; //[1, 2, 3, 4, 5, 6]
基於在對象之間直接構建繼承關係的理念,能夠用object()來接收父對象,並返回一個以該父對象爲原型的
新對象。
function object(p){ function F(){}; F.prototype = p; return new F(); }
var twoD = { name:'2d shape', dimensions:2 } function triangle(s,h){ var that = object(twoD);//把twoD對象全屬性拷貝進that對象 that.name = 'Triangle'; that.getArea = function(){return this.side * this.height / 2}; that.side = s; that.height = h; return that; }
實現繼承的方法大體上分爲兩類:
未完成
window.open('新URL','新窗口名','以逗號分割的功能性列表') window.close(); window.moveTo(x,y); window.moveBy(x,y); window.resizeTo(x,y); window.resizeBy(x,y); window.alert(); window.prompt(); //點擊確認返回相應文本,點擊取消返回null window.confirm();//點擊確認返回true,點擊取消返回false window.setTimeout();//指定多長時間後執行代碼 window.setInterval();//指定每隔多長時間執行代碼
navigation.userAgent是一個用戶瀏覽器識別的長字符串,但不要過度依賴這種用戶代理字符串,
瀏覽器能力檢測是更好地選擇
localtion對象的完整屬性:
location對象的方法:
history.forward();history.back();
screen.width(); screen.availwidth();
hasChildNodes()方法用於判斷一個節點是否存在子節點 hasAttributes()方法用於檢查該元素中書否存在屬性 document.documentElement.childNodes.length; //2 //任何節點均可以經過自身的parentNode來訪問它的父節點 document.documentElement.parentNode; //<html> document.getElementsByTagName(); document.getElementsByName(); document.getElementById(); nextSibling/previousSibling; firstChild/lastChild
createElement(); var myp = document.createElement('p'); createTextNode();//新建文本節點 appendChild(); document.body.appendChild(myp); cloneNode(true)//true深拷貝 false淺拷貝 insertBefore(要插入的節點,參照節點); replaceChild(要插入的節點,要替換的節點) removeChild(要移除的節點);
addEventListener('事件類型',函數指針[,false]); removeEventListener('事件類型',函數指針[,false]); //匿名函數所定義的監聽器是不能被移除的
該方法基於某一節點對象來調用,第三個參數決定代碼是否採用事件捕捉,可選的,爲了適應更多的瀏覽器,咱們通常將其設置爲false,即採用事件冒泡。
//建立xhr對象 var xhr; if(window.XMLHttpRequest){ xhr = new XMLHttpRequest(); }else{ xhr = new ActiveXObject("Microsoft.XMLHTTP") } //設置一個能觸發readystatechange事件的事件監聽器,及處理響應程序 xhr.onreadystatechange=function(){ if (xhr.readyState==4 && xhr.status==200){ console.log(xhr.responseText); } } //open(請求類型,請求目標URL,是否異步請求) xhr.open('GET','somefile.txt',true); //發送請求 xhr.send('')
2.3 function include(js){ var script = document.createElement('script'); script.src = js; document.body.appendChild(script); } include('somescript.js'); 3.1 var myevent = { addListener:function(el,type,fn){ if(typeof window.addEventListener === 'function'){ myevent.addListener = function(el,type,fn){ el.addEventListener(type,fn,false); }; }else if(typeof window.attachEvent === 'function'){ //code for IE myevent.addListener = function(el,type,fn){ el.attachEvent('on'+type,fn); }; }else{ // code for older browsers myevent.addListener = function(el,type,fn){ el['on' + type] = fn; }; } myevent.addListener(el,type,fn); }, removeListener : function(el,type,fn){ if(typeof window.removeEventListener === 'function'){ myevent.removeListener = function(el,type,fn){ el.removeEventEventListener(type,fn,false); }; }else if(typeof window.detachEvent === 'function'){ //code for IE myevent.removeListener = function(el,type,fn){ el.detachEvent('on'+type,fn); }; }else{ // code for older browsers myevent.removeListener = function(el,type,fn){ el['on' + type] = null; }; } myevent.removeListener(el,type,fn); }, getEvent:function(event){}, getTarget:function(event){}, stopPropagation:function(event){}, preventDefault:function(event){} } 4.1 var ajax ={ request:function(url,requestType,queryString){ var xhr; if(window.XMLHttpRequest){ xhr = new XMLHttpRequest(); }else{ xhr = new ActiveXObject("Microsoft.XMLHTTP") } xhr.onreadystatechange = function(){ if (xhr.readyState == 4 && xhr.status == 200){ console.log(xhr.responseText); } } xhr.open(requestType,url,true); xhr.send(''); } } ajax.request('some.txt','get');
爲了減小命名衝突,最好的辦法是將變量和方法定義在不一樣的命名空間中,這種方法的實質是隻定義一個全局變量,
並將其餘的方法和屬性定義爲該變量的屬性。
var mySpace = {}; mySpace.event = { addListener:null, removeListener:null …… } if(typeof window.addEventListener === 'function'){ mySpace.event.addListener = function(el,type,fn){ el.addEventListener(type,fn,false); }; mySpace.event.removeListener = function(el,type,fn){ el.removeEventListener(type,fn,false); }; }else if(typeof window.attachEvent === 'function'){ //code for IE mySpace.event.addListener = function(el,type,fn){ el.attachEvent('on'+type,fn); }; mySpace.event.removeListener = function(el,type,fn){ el.detachEvent('on'+type,fn); }; }else{ // code for older browsers mySpace.event.addListener = function(el,type,fn){ el['on' + type] = fn; }; mySpace.event.removeListener = function(el,type,fn){ el['on' + type] = null; }; }
var mySpace = {}; mySpace.event = { addListener:function(el,type,fn){ if(typeof window.addEventListener === 'function'){ mySpace.event.addListener = function(el,type,fn){ el.addEventListener(type,fn,false); }; }else if(typeof window.attachEvent === 'function'){ //code for IE mySpace.event.addListener = function(el,type,fn){ el.attachEvent('on'+type,fn); }; }else{ // code for older browsers mySpace.event.addListener = function(el,type,fn){ el['on' + type] = fn; }; } mySpace.event.addListener(el,type,fn); } };
該模式適用於有不少參數的函數或方法
用單個對象來替代多個參數有如下幾點優點:
var myapp = {}; myapp.dom = {}; myapp.dom.Button = function(text,conf){ var type = conf.type || 'submit'; var font = conf.font || 'microsoftyahei'; //…… } //使用方法以下: var config = { font:'Arial,Verdana,microsoftyahei', color:'#fff' }; new myapp.dom.Button('lalala',config);
(function(){ // code in here })() //該模式特寫適用於某些腳本加載時所執行的一次性初始化工做
構造器返回的是新建對象的this指針,咱們可使用這些方法所返回的實例來調用其餘方法
document.body.appendChild( new mySpace.dom.Element('span') .setText('hello') .setStyle('color','red') );
var obj = JSON.parse(xhr.responseText);