對象是一種數據的集合,數據格式爲鍵值對。javascript
對象字面量以"{}"做爲邊界,由多個鍵值對組成,鍵與值經過":"隔開,鍵值對之間經過","隔開css
var obj = {name:"terry",age:12,gender:"male"};
使用系統內置的對象構造函數Object()html
var obj = new Object(); //等價於var obj = {}
obj是對象實例,構造函數是建立對象實例時使用的模板vue
使用自定義的對象構造函數,例Student()html5
var stu = new Student();
(用於讀寫)java
對象.屬性node
var obj = {name:"terry",age:12,gender:"male"}; var name = obj.name; obj.name = 'terry';
對象[變量]mysql
var name = 'age'; obj[name];
打印出某個對象中全部的屬性jquery
for(var key in obj){ }
依次從obj中獲取屬性名賦值給key,經過obj[key]訪問屬性值 (屬性名若爲變量,則必須經過中括號方式訪問變量值)es6
將對象轉換成字符串
方便網絡傳輸(http/tcp/ip協議中不容許傳輸對象,只容許傳輸字符串和字節流),解決對象在io中傳遞的問題。
var obj = {name:'user'} obj.toString() //'[object Object]'
var obj = {name:'user'} JSON.stringify(obj) //'{"name":"user"}'
var qs = require('querystring') qs.stringify(obj)
全部構造函數的父構造函數,全部的構造函數都直接間接的繼承Object。全部的實例對象均可以調用其構造函數及其父構造函數的原型中的方法:
Object.prototype.constructor() //輸出建立該對象時使用的構造函數 Object.prototype.toString() //默認狀況下輸出[object object] Object.prototype.valueOf() Object.prototype.hasOwnProperty() //判斷某一個屬性是否是屬於當前對象 Object.prototype.isPrototypeOf() //指定的對象是否在本對象的原型鏈中 Object.prototype.propertyIsEnumerable() //指定的屬性是否可枚舉 Object.prototype.toSource()
obj的構造函數是Object,因此obj能夠調用Object.prototype的方法
var obj = {}
obj.toString();
arr的構造函數是Array,Array繼承Object,所以,arr能夠調用Array.prototype及Object.prototype中的方法
var arr = new Array(3);
arr.toString();
delete 對象.屬性
對比java對象,js對象有哪些特殊的地方
1. js對象的屬性能夠被刪除,java對象屬性是固定的 2. js對象的屬性能夠隨意添加,java對象屬性是固定的 3. js對象能夠經過字面量及構造函數來獲取,java對象只能經過類構建
//student有且只能有兩個屬性 class Student{ private String name; private Integer age; public void setName(String name){ this.name = name; } public String getName(){ return this.name; } } Student student = new Student();
var obj = { name:"terry" //name是能夠迭代的,是可讀可寫 }
假設:
當對象屬性的值發生變化的時候,我想知道?
var obj = { _name:"alxe", age:0 }; Object.defineProperty(obj,"name",{ configurable:true, writable:true, //enumerable:true; 使用set、get時不設置enumerable、value //value:"terry", set:function(v){ this._name = v; console.log("名字被修改"); }, get:function(){ return this._name; } }) obj.name = "terry"; console.log(obj.name);
當name、age、gender屬性發生變化的時候,都想檢測到.
Object.defineProperties(obj,{ name:{ }, gender:{ } })
數組是由若干個元素組成,元素能夠是任意的數據類型。經過索引(從0開始)訪問元素,數組的長度經過length屬性獲取。
var arr = [8,1,20,3,2,9]
var arr = new Array(); // var arr = []; var arr = new Array(5); // var arr = [,,,,]; arr[0] = "terry" arr[1] = "larry" //["terry","larry"]
//es6出現 Array.of(2); //[2] Array.of(2,3) //[2,3]
console.log(arr[0]); console.log(arr[100]); // undefined
length可讀可寫,能夠經過改變數組的長度來刪除數組元素
arr.length
api --> 應用程序編程接口-使用別人編寫的代碼
關注函數改變的是不是原數組自己
遍歷相關的方法
這些方法有個共同點,都須要傳遞一個回調函數做爲參數,回調函數都有三個形參,分別爲item,index,arr(可省略index/arr)
Array.prototype.forEach()
遍歷數組對象
參數:回調函數
返回值:undefined
//模仿forEach寫一個myForeach,其效果與forEach徹底相同 var arr = ["terry","larry","tom"]; arr.forEach(function(item){ console.log(item); }); //myForeach() Array.prototype.myForEach = function(handler){ //handler爲一個回調函數 for(var i=0;i<this.length;i++){ var item = this[i]; handler.call(this,item,i) } } arr.myForeach((item,index)=>{ console.log(item,index) })
元素是否都知足同一個條件
參數:回調函數須要返回boolean
返回值:boolean
是否有元素知足同一個條件
參數:回調函數須要返回boolean
返回值:boolean
返回回調函數返回true的元素的集合
參數:回調函數須要返回boolean
返回值:數組
返回回調函數返回值組成的數組
參數:回調函數,必定要返回值
返回值:數組
棧、隊列相關方法
向數組的末尾追加指定值
參數:任意值
返回值:數組長度
刪除並返回棧頂元素
參數:無
返回值:刪除的棧頂元素
出隊列
參數:無
返回值:刪除的隊列首部元素
將指定元素插入到隊列的首部
參數:任意值
返回值:插入後數組的長度
排序相關
原值發生改變;
Array.prototype.sort();
原值發生改變;
默認將數組元素轉換爲字符串,而後進行排序
sort容許接收一個比較器函數做爲參數,比較器函數接受兩個參數,
若是a > b,返回1,升序;若是a > b,返回-1,降序
arr.sort(function(a,b){ if(a>b){ return 1; }else{ return -1 } })
//提供一個函數,接受屬性做爲參數,要求按照name/age/grade進行排序 var arr = [{ name:"terry",age:19,grade:98 },{ name:"larry",age:12,grade:94 },{ name:"tom",age:15,grade:91 }] function sort(array,property){ array.sort((function(prop){ return function(a,b){ if(a[prop] > b[prop]){ return 1; } else { return -1; } } })(property)) } sort(arr,'age')
閉包:函數內部嵌套函數,內部函數擁有外部函數的變量,內部函數與外部函數的這個變量就組成了閉包。
截取
slice(begin,end)(原值不改變)
[1,2,3,4].slice(1); //[2,3,4] [1,2,3,4].slice(1,3); //數組個數爲3-1
splice(begin,num,x,x,...)(原值改變)(功能更強大)
begin:開始位置,num:刪除的元素個數,x,x,x:插入的元素
返回刪除的元素組成的數組
[1,2,3,4,5].splice(2,2) //[3,4] [1,2,3,4,5,6].splice(3,0,2,2,2) //運行後的數組結果:[1,2,3,2,2,2,4,5,6]
var arr0 = JSON.parse(JSON.stringify(arr))
var arr1 = arr.slice(0)
var arr2 = [...arr]
拓展運算符(es6)
函數也是對象,是一個引用數據類型。
無論是普通函數仍是構造函數,本質是徹底同樣的,只不過爲了區分它們,咱們將構造函數的函數名大寫
函數聲明與var聲明變量相似,都會有變量的提高。容許在函數聲明前調用函數
let result = add(1,2); // 能夠執行 function add( a, b){ return a + b; }
相似於普通的賦值表達式,變量會提高,可是函數初始化不會被提高。
add(); // 報錯! var add = function(a,b){ return a + b; }
只有在函數的執行過程當中,內部屬性才能被肯定
兜底對象(全局)
瀏覽器:window nodeJs:global
arguments
保存函數的全部實參,是一個類數組對象。
arguments.callee 指向當前函數,經常使用於遞歸函數。可是在嚴格模式'use strict'下沒法使用
var foo = function(a,b){ console.log(arguments) //{'0':1,'1':2,'2':3} } foo(1,2,3)
//求階乘 function foo(num){ if(num==1){ return 1; }else{ return arguments.callee(num-1)*num //更換函數名字時,不用考慮函數內部的名字更換 } }
this
當前的執行環境對象
與函數的調用方式有關
若是使用"()"調用函數,查看"()"是不是函數名,若是是,查看函數名前有沒有點".",沒有點"."this指向全局對象。有"."this指向點前面的那個對象。
function test(){ function bar(){ console.log(this) } bar(); } test(); //this-->global,由於調用bar()時,前面沒有'.'
var foo = function(a,b){ return a+b; }
var foo = (a,b)=>{ return a+b; //a+b;若大括號內只有一條語句,且該語句爲返回值語句,那麼{}也可省略 } //箭頭函數
箭頭函數通常用於回調函數,是回調函數的簡寫。
箭頭函數中的this指向包含它的外部函數的this,因此箭頭函數通常放在外部函數裏面,若箭頭函數外沒有外部函數,則this爲{}。
function foo(){ ["terry","larry"].forEach((item)=>{ console.log(this,item); }) } foo(); //global foo.call({}) //{} foo.call({name:"terry"}) //{name:"terry"}
new Vue({ el:"#app", data:{ students:[] student{} }, methods:{ // 加載學生信息 loadStudents(){ // this 指向vue對象 $.get('/findAllStudent',(students)=>{ // this指向外部函數this,也就是指向vue對象 this.students = students; //自定義屬性 }) } } })
函數是一種特殊對象,默認狀況下,一個函數都會有一個原型對象與之對應,函數中有個指針prototype指向原型對象,原型對象中有個constructor指向函數,你中有我,我中有你。
fun.prototype.constructor === fun //true
函數能夠做爲返回值【函數定製】
var arr = [{age:12},{age:3}]; arr.sort((function(key){ return function(a,b){ if(a[key]>b[key]){ return 1; }else{ return -1; } } })('age'))
var pattern = /abc/igm //abc-->正則表達式 //igm-->模式
var pattern = new RegExp("abc","igm");
測試目標字符串是否匹配正則表達式
RegExp.prototype.exec();
從目標字符串中獲取符合正則表達式的字符串
若是正則表達式中有修飾符‘g',在pattern中會維護lastIndex屬性,即記錄下一次開始的位置,當第二次執行exec()時,從lastIndex開始檢索。若沒有’g‘修飾符,則每一次都從開始位置進行檢索。
var str = "my phone is 18812344321, my emil is licy@briup.com, my name is charles, my friend is jacky, his phone is 17751229900, my friend is tom, his phone is 15912344432." function search(str){ var pattern = /((188)|(177)|(159))\d{8}/g; var result; while(result = pattern.exec(str)){ console.log(result[0],pattern.lastIndex); } } //查詢出全部符合模式的內容
獨立學科,用於匹配字符串。經常使用於檢索,論文查重,爬蟲,表單驗證。
默認是貪婪匹配,對於數量來講,儘量多得去匹配。若是但願非貪婪匹配,在數量詞後添加?
var str = "hello world" var pattern = /\w{1,5}?/ //優先匹配1個字符
使用分隔符'|'分割供選擇的字符,選擇項匹配次序爲從左至右。
url --> 協議://ip:port/path
var str = "my website url is http://127.0.0.1:80/cms/index.html , my database url is jdbc:mysql://127.0.0.1:3306/cms , this is ok" var pattern = /(http|jdbc\:mysql|ftp)\:\/\/(((\d{1,3})\.){3}((\d{1,3})))(\:(\d{2,4}))?(\/[\w\.]*)*/ig
每個括號都是一個分組
/(http|jdbc:mysql|ftp)://(w{1,3}.){+}:?(d{2,4})?(/[w.])/ig
pattern.exec(str)
result[0] 整個模式匹配的結果
result[1] 第一個分組匹配的結果
result[2] 第二個分組匹配的結果
...
1 引用第一個分組匹配的結果
var pattern = /(\d{1,3})\1/g; pattern.exec(192.12) //null pattern.exec(192.192.) //['192.192.','192.'...]
2 引用第二個分組匹配的結果
檢索出全部的手機號。
(牛客網 - 正則表達式)
基本數據類型默認是沒法調用Object原型中的方法,爲了豐富基本數據類型的功能,即基本數據類型的變量也能夠調用方法,js爲此實現自動裝箱功能【當調用基本數據類型變量的方法的時候,會自動轉換爲其構造函數的實例對象】
Number
var a = 3; a.toString(); //本來是沒法調用該方法的,但因爲js將其自動裝箱,使其自動實現了‘a = new Number(a)’代碼,即將其轉換成爲了引用類型的變量,所以其能夠調用Number.prototype和Object.prototype中的方法 console.log(a); //當變量進行正常計算時,會將其自動拆箱
參數均可覺得正則表達式,若是爲字符串,會先轉化爲正則表達式
String.prototype.split()
將字符串根據指定參數進行切割,返回一個數組
"hello".split() //['hello'] "hello".split("") //['h','e','l','l','o'] "terry#larry".split(/\#/) //['terry','larry'],等價於"terry#larry".split('#')
不支持全局搜索
與RegExp.prototype.test相似,返回匹配模式的字符串的索引,若是沒有匹配的結果則返回-1
String.prototype.match()
與RegExp.prototype.exec相似
返回值爲替換後的結果
返回截取後的結果,原值不改變
len表示截取的長度
返回截取後的結果,原值不改變
與slice相同
消除字符串左右兩邊的空格,原值不改變
...
構造函數
Date.prototype.getTime();
返回一個時間戳 ,即當前時間到格林威治標準時間的毫秒數(可使用時間戳轉換成任意的數據格式)
var now = new Date(); //2020-08-10T05:48:49.439Z--當前時間 now.getTime(); //1597038529439--時間戳 var d = new Date(1597038529439) //2020-08-10T05:48:49.439Z
是對象,不是函數
向上舍入
向下舍入
如何建立一個對象?
字面量/Object - 純對象,只能Object.prototype中的方法,而且類型沒法細分。
類型細分(特定對象能夠調用特定方法):
工廠函數模式
function PersonFactory(name,age,gender){ var p =new Object(); p.name = name; p.age = age; p.gender = gender; return p; } var p = PersonFactory("terry",12,"gender");//p本質仍是一個Object p.constructor // Object
問題:對象類型沒法細分。
構造函數模式(構造函數使用new來調用)
function Person(name,age,gender){ this.name= name; this.age = age; this.gender = gender; this.sayName = function(){ console.log("my name is",this.name); } } //若是該函數使用new來調用,1) this指向當前實例對象2)函數執行完畢後,會將當前實例對象返回 var p1 = new Person("terry",12,"male"); // p1指向實例對象 var p2 = Person("terry",12,"male"); // p2爲undefined,由於沒有實例對象返回(this指向全局對象)
解決:對象類型細分的問題
問題:內存浪費。若是將函數存放到實例對象,每一個實例對象擁有一個獨自的函數,而這樣是毫無心義。
//解決了內存問題,但不成熟 function sayName(){ console.log("my name is",this.name); } function Person(name,age,gender){ this.name= name; this.age = age; this.gender = gender; this.sayName = sayName;//引用地址傳遞 }
構造函數(實例屬性)+原型(實例方法,共享屬性)
基本屬性維護在實例中,共同的方法維護構造函數的原型中。
function Person(name,age,gender){ this.name= name; this.age = age; this.gender = gender; } Person.prototype.sayName = function(){ console.log("my name is",this.name); } Person.prototype.sayAge = function(){ console.log("my age is",this.age); } var p = new Person("terry",12,"male");
問題:原型方法封裝性較差
加強版
function Person(name,age,gender){ this.name= name; this.age = age; this.gender = gender; } Person.prototype = { constructor:Person, // 核心點 sayName :function(){ console.log("my name is",this.name); }, sayAge :function(){ console.log("my age is",this.age); } } var p = new Person("terry",12,"female")//實例對象p的__proto__值指向的是其構造函數中prototype值所指向的原型對象。 //{}會建立一個新對象,同時將Person構造函數的prototype值指向該新創建的對象,而新對象的__proto__指向的倒是Object函數的原型對象的地址,若是調用‘p.constructor’返回的將是[Function:Object]。所以爲了使其返回的是Person函數,咱們須要在這個新建立的對象中指明constrcutor所對應的構造函數爲Person。
繼承即實例對象能夠調用其構造函數原型中的方法以及其構造函數的父構造函數原型中的方法...
Dog繼承Animal
dog -> Dog.prototype -> Animale.prototype
function Aniaml(name,age){ this.name = name; this.age = age; } Animal.prototype = { constructor :Animal, sayName:function(){ console.log('my name is ',this.name); }, sayAge:function(){ console.log('my age is ',this.age); } } function Dog(name,age,gender){ //借用構造函數 Animal.call(this,name,age); /* this.name = name; this.age = age; */ this.gender = gender; }
Dog實例若想調用父構造函數原型中的方法,則要使用原型鏈繼承。
//子構造函數的原型指向父構造函數的實例 Dog.prototype = new Animal();//繼承 Dog.prototype.constructor = Dog; Dog.prototype.sayGender = function(){ }//其餘操做必須在繼承完成以後 var dog = new Dog('wang',12,'母')
dom -- > 瀏覽器將html/css轉換爲js對象,而後咱們經過js操做這些對象。
一般不多本身建立dom對象,由於瀏覽器已經轉換了。但咱們須要在html中添加結構時須要本身建立dom對象,再由瀏覽器轉換成html/css。
var dom = document.getElementById('');//document是瀏覽器的內置對象,瀏覽器將html轉換成對象,此document表明的則是整個html頁面。dom是js對象,是HtmlDivElement的實例對象,因此它能夠調用HtmlDivElement,HtmlElemnet,Element,Node,Object中的方法
繼承關係:
Node
Element 元素節點(標籤轉換的元素對象)*
Document 文檔節點(表示當前html文檔)*
節點信息相關屬性
文本-3;註釋-8;元素-1;文檔-9
Node.prototype.nodeName
層次結構相關屬性
Node.prototype.childNodes
返回一個類數組對象
var dom = document.getElementById("content"); var nodelist = dom.childNodes; //返回類數組對象 var arr1 = Array.prototype.slice.call(nodelist,0); //轉換爲數組方法一 var arr2 = Array.from(nodelist); //轉換爲數組方法二
方法
是經過父節點對象來調用
參數爲true,表示除了克隆當前對象,還克隆子元素
Document.prototype.body
Document.prototype.forms
Document.prototype.images
Document.prototype.charset
Document.prototype.doctype 判斷當前網頁是html4仍是html5
方法:
元素節點查詢
返回第一個匹配的element
返回全部匹配的element,並將其放入一個類數組對象中。
節點建立
var new_h3 = document.createElement("h3"); new_h3.innerText = "end" //該屬性是HtmlElement內的屬性
元素節點
設置標籤內的文本節點
設置標籤內的html代碼(能夠將字符串解析爲標籤)
獲取(只能獲取到內置樣式)或設置樣式
方法
將在將來的某個時刻執行,由瀏覽器調用,而且瀏覽器會將事件對象傳遞給該函數的參數。
事件類型
<a>標籤有自動跳轉的默認事件行爲
事件冒泡
元素具備嵌套關係
<div class="outer"> <div class="center"> <div class="inner"></div> </div> </div>
(當咱們點擊inner的時候,實際上也點擊center、outer。)
事件捕獲: outer -> center -> inner
但事件處理函數的調用默認是按照事件冒泡的順序來調用
事件冒泡: inner -> center -> outer
操做的元素
事件源.on事件類型 = 事件處理函數(事件對象){
}
dom.onClick = function(event){
}
綁定方式:
事件的目標元素(操做的元素)
事件觸發時候的座標
阻止事件的默認行爲
取消事件冒泡
將事件綁定在父元素上而不是子元素上
<body> <button id="add">添加</button> <table id="tbl"> <thead> <tr> <th>姓名</th> <th>操做</th> </tr> </thead> <tbody> <tr> <td>zyj</td> <td> <a href="" id="del">刪除</a> <a href="" id="fix">修改</a> </td> </tr> </tbody> </table> <script> var $add = document.querySelector("#add"); var $tbl = document.querySelector("#tbl"); //添加 $add.onclick = function(){ var $new_tr = document.createElement("tr") $new_tr.innerHTML=` <td>`+Math.random()+`</td> <td> <a href="" id="del">刪除</a> <a href="" id="fix">修改</a> </td> ` $tbl.children[1].appendChild($new_tr); } //刪除 $tbl.onclick = function(event){ //事件綁定在父表格上,經過target,即點擊的目標元素來確認具體事件行爲。 var target = event.target; //每點擊一次刪除連接,該事件就會執行一次。 if(target.nodeName == 'A'){ switch(target.getAttribute("id")){ case "del": target.parentElement.parentElement.parentElement. removeChild(target.parentElement.parentElement); break; case "fix": alert("修改"); break; } } event.preventDefault(); } //下面的方法不可行,由於在html初次執行時就已經肯定了全部的刪除連接,並設置了事件行爲,但表格是動態增加的,即刪除連接的個數也在動態增加。 // var delliset = document.querySelectorAll("#del"); // Array.from(delliset).forEach((item)=>{ // item.onclick = function(){ // item.parentElement.parentElement.parentElement.removeChild(item.parentElement.parentElement); // event.preventDefault(); // } // } </script> </body>
jquery 其實是對於dom api的封裝,讓用戶使用dom方法變得更加簡潔。
業務 | javascript | jquery |
---|---|---|
選擇元素 | querySelector | 選擇器$(" ") |
dom元素 | 沒法進行批量操做 | 能夠實現批量操做 |
事件綁定 | 兼容性較差 | 兼容性,高效,批量,方法簡潔 |
dom層級關係 | 操做繁雜 | 操做簡練 |
jQuery對象是一個類數組對象,類數組對象中的元素是Element元素
jquery對象 -> dom對象,即把類數組對象中的元素取出。
<script> var $btn_add = $("#add"); var $tbl_user =$("#tbl"); //刪除 $tbl_user.on('click','a',function(event){ var target = $(event.target); switch(target.attr("id")){ case "del": // 移除節點 target.parents("tr").remove() break; case "fix": alert('修改'); break; } return false; }) // 添加 $btn_add.on('click', function(){ // 虛擬dom $( ` <tr> <td> <input type="checkbox"> </td> <td> `+Math.random()+` </td> <td> 男 </td> <td> <a href="" class="btn_del">刪除</a> <a href="" class="btn_edit">修改</a> </td> </tr> `).appendTo($('#tbl > tbody')) }); </script>
//超時調用 var flag = setTimeout(function(){ //通過1000ms之後調用回調函數,只調用一次。1000ms不可靠 },1000) //flag爲超時調用函數的一種標識 console.log(flag); //異步,先打印flag值 clearTimeout(flag); //取消超時調用
//間歇調用 var flag = setInterval(function(){ console.log('時間到了') //當回調函數的執行內容相同時,控制檯只會顯示一次輸出內容 },1000) //每隔1000ms調用一次回調函數
如何使用超時調用來模仿一個間歇調用
(企業級不會直接使用這些提示框)
window.href = "" //window是瀏覽器的全局對象,var變量即被提高到window中
方法做用域,方法執行環境
方法執行完畢後,函數內部聲明的變量會被釋放
var a = 3; function foo(){ var b = 4; for(var i=0;i<10;i++){} console.log(i); //10--變量沒有局部做用域 } foo(); console.log(window.a); //3 console.log(window.b); //undefined--方法做用域
如何模擬一個局部做用域
function foo(){ if(true){ var c = 1; //指望c擁有局部做用域 } console.log(c) //1 } ======================= function foo(){ (function(){ if(true){ var c = 1; } })(); }
window.onscroll = function(){ }
window.history.go(1); //前進1頁 window.history.back();
window.onload = function(){ //當頁面加載完畢後 var hash = window.location.hash.slice(1); //獲取路由 switch(hash){ case "/space": break; case "/home": break; } }
異步的javascript和xml (json),主要用於先後臺分離開發中數據的交互,佔據咱們開發的50%以上。
//異步 function(){ 查詢文章信息 ajax 查詢用戶信息 ajax 查詢評論信息 ajax console.log('end'); } //三個查詢同時進行,因爲網絡等緣由,返回結果的時間是不肯定的。所以,console.log("end")最早執行
//數據傳遞 -----同步方式(返回)----- function foo(){ return ""; } var a = foo(); -----異步方式(回調)----- function foo(handler){ 將來的某個時刻才能獲取到 handler("結果") } foo(function(a){});
實現過程:
實例化XMLHttpRequest
var xhr = new XMLHttpRequest()
設置請求行
xhr.open(method,url)
設置請求頭
(請求方式method = "POST"的時候纔會設置Content-Type)
xhr.setRequestHeader(key,val)
設置請求體
(請求方式method = "POST"的時候纔會傳遞data)
xhr.send(data)
監聽請求狀態
xhr.onreadystatechange = function(){ if(this.readyState === 4){ //請求正常發送到服務器端,響應到達客戶端而且已被解析爲客戶端可用的格式 if(this.status === 200){ console.log(this.response); } } }
status:
200 ok 500 後端接口異常 404 找不到