寫在開頭:
為了學(xué)習(xí)方便,js程序分成兩個(gè)階段學(xué)習(xí),JS初級(jí)和js高級(jí)階段,js高級(jí)有很多需要理解的概念,重在理解!讓我們愉快的開始學(xué)習(xí)吧。
一、面向對(duì)象
1、對(duì)象,JavaScript是一種面向?qū)ο缶幊?OOP)語(yǔ)言。一種編程語(yǔ)言可以被稱為面向?qū)ο蟮?,它為開發(fā)者提供了四種基本功能:
1)抽象
2)繼承(父級(jí)對(duì)子級(jí)功能的開放和共享)
3)封裝(將抽象得到的數(shù)據(jù)和行為相結(jié)合,形成一個(gè)整體,對(duì)外隱藏屬性和實(shí)現(xiàn)細(xì)節(jié),只對(duì)外提供接口)
4)多態(tài)(同一操作作用于同類但不同的對(duì)象上面,可以產(chǎn)生不同的解釋和不同的執(zhí)行結(jié)果
對(duì)象是由屬性和方法。如果屬性包含一個(gè)函數(shù),它被認(rèn)為是一個(gè)對(duì)象的方法,否則,該屬性被認(rèn)為是一個(gè)屬性。
2、創(chuàng)建對(duì)象方法(自定義對(duì)象):
1)字面量法
字面量創(chuàng)建對(duì)象
var car = {
name:"didi",
age:5
run:function(){
console.log("跑的快")}
};
2)new+構(gòu)造函數(shù)
var obj = new Object();
3)工廠模式創(chuàng)建
創(chuàng)建工廠函數(shù)
function factory(name,age){
var newObj = {};
newObj.name = name;
newObj.age = age;
newObj.say = function(){
console.log(this.name);};
return newObj;}
使用構(gòu)造函數(shù)創(chuàng)建對(duì)象
var person = factory("tom",28);
4)動(dòng)態(tài)原型方式創(chuàng)建
3、對(duì)象屬性的增刪改查
Obj[屬性名]注意區(qū)別!屬性加雙引號(hào),變量不加Obj[變量]
car.name =“baoma”
4、對(duì)象屬性的getter()、setter()
我們知道,對(duì)象屬性是由名字、值和一組特性(attribute)構(gòu)成的。在ECMAScript 5中,屬性值可以用一個(gè)或兩個(gè)方法替代,這兩個(gè)方法就是getter和setter。由getter和setter定義的屬性稱做「存取器屬性(accessor property)」,它不同于「數(shù)據(jù)屬性(data property)」,數(shù)據(jù)屬性只有一個(gè)簡(jiǎn)單的值。
當(dāng)程序查詢存取器屬性的值時(shí),JavaScript 調(diào)用getter方法。這個(gè)方法的返回值就是屬性存取表達(dá)式的值。當(dāng)程序設(shè)置一個(gè)存取器屬性的值時(shí),JavaScript 調(diào)用setter方法,將賦值表達(dá)式右側(cè)的值當(dāng)做參數(shù)傳入setter。從某種意義上講,這個(gè)方法負(fù)責(zé)「設(shè)置」屬性值。可以忽略setter方法的返回值。
和數(shù)據(jù)屬性不同,存取器屬性不具有可寫性(writable attribute)。如果屬性同時(shí)具有g(shù)etter和setter方法,那么它是一個(gè)讀/寫屬性。如果它只有g(shù)etter方法,那么它是一個(gè)只讀屬性。如果它只有setter方法,那么它是一個(gè)只寫屬性,讀取只寫屬性總是返回undefined。定義存取器屬性最簡(jiǎn)單的方法是使用對(duì)象直接量語(yǔ)法的一種擴(kuò)展寫法。例如:
varo = {// 普通的數(shù)據(jù)屬性data_prop: value,// 存取器屬性都是成對(duì)定義的函數(shù)get accessor_prop() {/*這里是函數(shù)體 */},? ? set accessor_prop(value) {/* 這里是函數(shù)體*/}};
存取器屬性定義為一個(gè)或兩個(gè)和屬性同名的函數(shù),這個(gè)函數(shù)定義沒有使用function關(guān)鍵字,而是使用get或set。注意,這里沒有使用冒號(hào)將屬性名和函數(shù)體分隔開,但在函數(shù)體的結(jié)束和下一個(gè)方法或數(shù)據(jù)屬性之間有逗號(hào)分隔。
set可以用于修改私有屬性
get獲取值
5、對(duì)象序列化(serialization)是指將對(duì)象的狀態(tài)轉(zhuǎn)換為字符串,也可將字符串還原為對(duì)象。ECMAScript 5提供了內(nèi)置函數(shù)JSON.stringify()和JSON.parse()。
6、for-in循環(huán)遍歷對(duì)象
7、屬性查找:首先在自身中查找,如果沒有沿著原型鏈逐級(jí)向上查找,最后沒有找到返回undefined
8、靜態(tài)方法:給構(gòu)造函數(shù)添加的方法和屬性。
二、高級(jí)函數(shù)
1、Js中函數(shù)屬于一等公民,幾乎可以出現(xiàn)在任何場(chǎng)景中。(作為參數(shù)、函數(shù)嵌套函數(shù)、函數(shù)作為返回值
2、函數(shù)分類:官方定義的函數(shù)(輸出函數(shù)都document、alert()、console.log()、輸入函數(shù)prompt()、變量類型的轉(zhuǎn)換函數(shù)Number()、parsenInt()、paeseFloat()、Boolean()、isNaN()、數(shù)學(xué)函數(shù)、Math.random();Math.random()*(n-m)+m、DOM document.getElementByid())、構(gòu)造函數(shù)、自定義函數(shù)
js中絕大數(shù)的函數(shù)的原型都是object類型的,只有一個(gè)例外,就是Function他的原型是一個(gè)function
3、創(chuàng)建函數(shù)方式:
1)function關(guān)鍵字聲明function add(){}
2)字面量方式聲明var say = function(){}
3)使用new Function創(chuàng)建函數(shù)對(duì)象var add = new Function(“a”,”b”);
var function_name = new Function(arg1, arg2, ..., argN, function_body)
創(chuàng)建ab數(shù)值互換函數(shù)注意形參需使用字符串
var fn = new Function("a", "b", "a = a + b; b = a - b; a = a - b; console.log(a); console.log(b);");
fn(10, 20);
4、函數(shù)作用域:形參、實(shí)參
Js中是以函數(shù)作為局部變量和全局變量區(qū)分,沒有塊元素。
變量聲明、函數(shù)聲明
5、this典型場(chǎng)景:
6、構(gòu)造函數(shù),特殊的函數(shù),用于創(chuàng)建同類對(duì)象
function Person(){
thhis.name = name;
this.age = age;
this.say(){
}
}
7、使用new關(guān)鍵字執(zhí)行構(gòu)造函數(shù)(實(shí)例對(duì)象)
var p1 = new Pereson();
8、構(gòu)造函數(shù)和普通函數(shù)的區(qū)別:
1)首字母大寫
2)內(nèi)部使用this關(guān)鍵字處理屬性賦值邏輯
3)構(gòu)造函數(shù)不使用return關(guān)鍵字返回新對(duì)象
4)使用new關(guān)鍵字執(zhí)行函數(shù)
構(gòu)造函數(shù)與實(shí)例:實(shí)例是new加構(gòu)造函數(shù)創(chuàng)建的對(duì)象,新對(duì)象叫做構(gòu)造函數(shù)的實(shí)例。實(shí)例與構(gòu)造函數(shù)之間是多對(duì)一的關(guān)系。
eg:一個(gè)Person函數(shù)可以創(chuàng)建無(wú)數(shù)個(gè)Person實(shí)例p1 p2 ...pn
new做的一些事兒:new在堆區(qū)開辟一片空間用來(lái)保存對(duì)象;返回堆區(qū)對(duì)象的引用地址。
三、原型:作用是為所有實(shí)例提供公共的空間,原型內(nèi)的屬性可以提供給構(gòu)造函數(shù)所有實(shí)例復(fù)用。
1、每一個(gè)函數(shù)對(duì)象都有一個(gè)私有原型屬性prototype,Person.prototype這個(gè)值是一個(gè)object類型的對(duì)象
實(shí)例(對(duì)象)都有一個(gè)__proto__屬性指向構(gòu)造函數(shù)的原型prototype
2、hasOwnProperty()函數(shù):用來(lái)判斷某個(gè)屬性是否是自身的私有屬性,是返回true, 原型中的屬性或不存在返回false
isprototype()判斷一個(gè)對(duì)象是否是另一個(gè)對(duì)象的原型。
In關(guān)鍵字可以判斷某個(gè)屬性對(duì)象是都可用,準(zhǔn)確說(shuō)對(duì)象自身私有屬性或者原型屬性總存在該屬性返回true
3、原型鏈:原型通過(guò)繼承關(guān)系鏈接到一起,組成的鏈型結(jié)構(gòu),叫做原型鏈。
原型是函數(shù)prototype屬性對(duì)應(yīng)的對(duì)象,而多個(gè)構(gòu)造函數(shù)相互繼承,將彼此的原型對(duì)象進(jìn)行關(guān)聯(lián),組成了一條鏈型結(jié)構(gòu)。
原型鏈從下級(jí)函數(shù)實(shí)例的__ptoto__開始 ?原型鏈的頂端Object.prototype.__proto__
4、繼承
繼承方式:原型繼承、借用構(gòu)造函數(shù)、組合繼承、ES6方法繼承
1)原型方式繼承:
Student.prototype = new Person();
將上級(jí)函數(shù)的實(shí)例,賦值給下級(jí)函數(shù)的原型
繼承目的:下級(jí)函數(shù)的實(shí)例提供多個(gè)可共用的原型
原型方式繼承:
優(yōu)點(diǎn):通過(guò)原型方式繼承,底層函數(shù)可以逐級(jí)向上復(fù)用上級(jí)函數(shù)原型空間
缺點(diǎn):下級(jí)函數(shù)無(wú)法復(fù)用上級(jí)函數(shù)的私有屬性初始邏輯,上級(jí)函數(shù)實(shí)例的私有屬性會(huì)進(jìn)入到下級(jí)函數(shù)的原型中,即使是undefined也會(huì)被當(dāng)做有效屬性查找
偽造、借用構(gòu)造函數(shù)方式的繼承:
優(yōu)點(diǎn):可以實(shí)現(xiàn)多繼承,還可以復(fù)用上級(jí)函數(shù)私有屬性初始化邏輯
缺點(diǎn):此種繼承和原型無(wú)關(guān),下級(jí)函數(shù)實(shí)例無(wú)法復(fù)用上級(jí)函數(shù)的原型
基于以上兩種繼承方式的優(yōu)缺點(diǎn),人們創(chuàng)造而第三種繼承方式: 組合方式繼承
原型繼承:
將上級(jí)函數(shù)的實(shí)例,賦值給下級(jí)函數(shù)的原型
繼承目的:下級(jí)函數(shù)的實(shí)例提供多個(gè)可共用的原型
注意!constructor屬性位于函數(shù)對(duì)象中。是原型默認(rèn)的兩個(gè)屬性之一,他的默認(rèn)值是原型所屬的函數(shù)。
當(dāng)對(duì)函數(shù)原型進(jìn)行覆蓋型操作時(shí),注意必須修正constructor屬性(原型繼承)
2)借用構(gòu)造函數(shù)繼承(經(jīng)典繼承)
關(guān)鍵代碼借用call()、apply()函數(shù)
function Student(name, age, stuNum, legs, eyes){
Person.call(this, name, age);
Animal.apply(this, [legs, eyes]);
// this.name = name;
// this.age = age;
this.stuNum = stuNum;}
call、appl繼承作用:
可以延長(zhǎng)作用域借用構(gòu)造函數(shù)方式支持多繼承
區(qū)別:兩者主要差異在于傳參call將函數(shù)需要的參數(shù)在第二個(gè)參數(shù)開始按順序傳遞,而apply只能講參數(shù)封裝成數(shù)組傳給函數(shù)
3)組合繼承(原型和組合繼承)
function Fruit(color, taste, size){
this.color = color;
this.taste = taste;
this.size = size;}
Fruit.prototype.grow = function(){
console.log("小蘋果長(zhǎng)大了!");}
創(chuàng)建蘋果構(gòu)造函數(shù)
function Apple(color, taste, size, price){
復(fù)用上級(jí)函數(shù)私有屬性初始化邏輯
Fruit.call(this, color, taste, size);
this.price = price;}
使用原型繼承方式,連接上下級(jí)函數(shù)原型
Apple.prototype = new Fruit();
Apple.prototype.bad = function(){
console.log("再不吃就爛了?。?!");}
創(chuàng)建實(shí)例測(cè)試?yán)^承效果
var apple = new Apple("red", "sweet", "big", 100);
apple.grow();
console.log(apple);
1、可以延長(zhǎng)作用域借用構(gòu)造函數(shù)方式支持多繼承
2、區(qū)別:兩者主要差異在于傳參call將函數(shù)需要的參數(shù)在第二個(gè)參數(shù)開始按順序傳遞,而apply只能講參數(shù)封裝成數(shù)組傳給函數(shù)
3、基于借用、偽造構(gòu)造函數(shù)方式的繼承,并沒有關(guān)聯(lián)上下級(jí)函數(shù)的原型,而是僅僅讓下級(jí)函數(shù)借用了上級(jí)函數(shù)初始化私有屬性的代碼。
4)ES6繼承
class Person{
constructor(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;}
walk(){
console.log("你好嗎");}
}
class Student extends Person{
constructor(name,age,sex,school,stu_id){
super(school,stu_id);
this.stu_id = stu_id;
this.school = school;}
run(){
console.log("400米");}
}
var student4 = new Student("北大","7號(hào)");
console.log(student4);
student4.run();
四、Ajax:是一種瀏覽器到服務(wù)器端通信技術(shù),通常使用腳本發(fā)送異步請(qǐng)求。
1、通信原理(核心步驟)
ajax通信過(guò)程控制,是通過(guò)監(jiān)聽readyState狀態(tài)碼來(lái)實(shí)現(xiàn)的,而監(jiān)聽是通過(guò)onreadystatechange事件監(jiān)聽屬性完成的
readyState分5個(gè)狀態(tài)
0):xhr對(duì)象創(chuàng)建
1):open初始化完成
2):send請(qǐng)求發(fā)送
3):開始接收返回?cái)?shù)據(jù)
4):數(shù)據(jù)接收完畢
注意!//XMLHttpRequest在絕大多數(shù)瀏覽器下都支持。而IE低版本下(ie6)不支持該構(gòu)造函數(shù),需要使用ActiveXObject該構(gòu)造函數(shù)需要使用對(duì)應(yīng)的參數(shù)構(gòu)造出通信對(duì)象["MSXML.XMLHttp.6.0","MSXML.XMLHttp.3.0","MSXML.XMLHttp"]
2、get和post的區(qū)別:get與post是http通信協(xié)議下兩種想后臺(tái)發(fā)送請(qǐng)求的方式。post允許傳遞參數(shù)相比get更大,get是k級(jí)別的數(shù)據(jù)量post是m級(jí)別的數(shù)據(jù)量;
post傳參數(shù)據(jù)放在數(shù)據(jù)報(bào)文內(nèi)部,而get參數(shù)拼接在url后面,post更安全;
get相比post方式請(qǐng)求更快,理論上能快一倍
3、jsonp跨域手段
4、baiduTemplate Javascript模板引擎:
應(yīng)用在前端模版系統(tǒng)或則后端JavaScript的環(huán)境發(fā)布頁(yè)面,它提供了一套模版語(yǔ)法,用戶可以寫一個(gè)模版區(qū)塊,每次根據(jù)傳入的數(shù)據(jù)生成對(duì)應(yīng)數(shù)據(jù)產(chǎn)生的Html,渲染不同界面效果;它的優(yōu)點(diǎn):愈發(fā)簡(jiǎn)單,學(xué)習(xí)成本極低,開發(fā)效率提升很大,采用javascript的原生語(yǔ)法,所以效率比較高, 默認(rèn)HTML轉(zhuǎn)義(防XSS攻擊),并且支持包括URL轉(zhuǎn)義等多種轉(zhuǎn)義,變量未定義自動(dòng)輸出為空,防止頁(yè)面錯(cuò)亂,功能強(qiáng)大,如分隔符可自定等多種功能。
五、動(dòng)畫
1、計(jì)時(shí)器的寫法(輪播圖)
2、鼠標(biāo)、鍵盤位置元素(推箱子游戲)
3、游戲(碰撞檢測(cè))
4、jQuery動(dòng)畫
六、一些重要的概念
1、變量聲明提升:js是一種腳本語(yǔ)言,執(zhí)行前沒有編譯過(guò)程,但是有預(yù)編譯階段。預(yù)編譯以代碼塊或文件為單位,首先檢查語(yǔ)法錯(cuò)誤,再做做變量聲明提升,最后做函數(shù)聲明提升。當(dāng)一個(gè)區(qū)塊內(nèi)代碼執(zhí)行前,js引擎會(huì)對(duì)該區(qū)域代碼進(jìn)行預(yù)編譯,將所有變量聲明提升到代碼最頂端,初始化為undefined。
2、函數(shù)聲明提升:預(yù)編譯階段,當(dāng)前作用域下所有函數(shù)對(duì)象會(huì)被創(chuàng)建完成。
預(yù)編譯作用:
1).語(yǔ)法錯(cuò)誤檢查,如果有錯(cuò)誤,不再執(zhí)行后續(xù)操作
2).變量聲明提升
3).函數(shù)聲明提升
3、函數(shù)柯里化:為函數(shù)執(zhí)行固定的參數(shù)固定參數(shù)從第二個(gè)參數(shù)開始按順序傳入。
核心思想:為在復(fù)用原函數(shù)邏輯代碼基礎(chǔ)上,為函數(shù)指定固定的參數(shù)。
function curry(fn){
var args = [].slice.call(arguments, 1);
return function(){
使用slice函數(shù)將實(shí)參維數(shù)組轉(zhuǎn)化為數(shù)組,下一部拼接
var innerArgs = [].slice.call(arguments);
固定參數(shù)列表拼接自定義參數(shù)列表
var argsFinal = args.concat(innerArgs);
執(zhí)行原有函數(shù) 只不過(guò)參數(shù)列表已經(jīng)被替換為新列表
return fn.apply(null, argsFinal)}}
4、同源策略:瀏覽器限制動(dòng)態(tài)訪問(wèn)非同源資源內(nèi)容。處于安全考慮下不允許使用ajax等異步加載技術(shù)非同源內(nèi)容,也防止外部?jī)?nèi)容惡意注入。同源三大要素:協(xié)議、ip和端口
5、回調(diào)函數(shù):作為主函數(shù)達(dá)到某些固定條件才會(huì)執(zhí)行的函數(shù)。通常作為主函數(shù)的參數(shù)傳入主函數(shù)中。
6、C/S通信客戶端/服務(wù)端通信 ?客戶端網(wǎng)游和服務(wù)器B/S瀏覽器/服務(wù)端通信 百度等
通信是端與端的數(shù)據(jù)交互
7、閉包:外部函數(shù)返回的,持有外部函數(shù)變量的,內(nèi)部函數(shù)。
8、匿名函數(shù):通常出現(xiàn)在不需要使用函數(shù)名執(zhí)行函數(shù)的場(chǎng)景。
9、垃圾回收:垃圾回收清理內(nèi)存中無(wú)用的對(duì)象,釋放內(nèi)存空間簡(jiǎn)稱GC。
主流垃圾回收方式有兩種:標(biāo)記清除是目前js主流垃圾回收機(jī)制,清除邏輯: 首先標(biāo)記內(nèi)存中所有對(duì)象,檢查不再運(yùn)行環(huán)境中的對(duì)象,取消標(biāo)記,檢查后 清除不帶有標(biāo)記的對(duì)象,釋放對(duì)應(yīng)空間。
2)引用計(jì)數(shù) 因?yàn)樯贁?shù)IE核心中bom dom對(duì)象仍使用c系列語(yǔ)言實(shí)現(xiàn),所以保留其引用計(jì)數(shù)垃圾回收方式 邏輯:當(dāng)一個(gè)對(duì)象在內(nèi)存存在一個(gè)引用,計(jì)數(shù)為1每多一個(gè)引用計(jì)數(shù)加一,當(dāng)垃圾回收?qǐng)?zhí)行時(shí),會(huì)檢查并銷毀計(jì)數(shù)為0的對(duì)象
js不推薦程序員主動(dòng)觸發(fā)垃圾回收,依賴js核心自動(dòng)的垃圾回收周期
垃圾回收中所有代碼執(zhí)行暫停,所以不建議程序員自助調(diào)用回收函數(shù)觸發(fā)回收。
垃圾回收優(yōu)化:采用分批次分優(yōu)先級(jí)等算法,盡量減少單次垃圾回收耗時(shí)。
10、事件委托:通過(guò)上級(jí)節(jié)點(diǎn)監(jiān)聽事件處理下級(jí)節(jié)點(diǎn)事件。
事件冒泡:當(dāng)前節(jié)點(diǎn)觸發(fā)某類事件時(shí),也會(huì)從當(dāng)前節(jié)點(diǎn)開始逐級(jí)先上,觸發(fā)上級(jí)節(jié)點(diǎn)的同類事件。event對(duì)象的target屬性可以返回觸發(fā)當(dāng)前的dom對(duì)象
事件委托優(yōu)點(diǎn):可以減少頁(yè)面綁定事件數(shù)量,提高頁(yè)面性能
當(dāng)子節(jié)點(diǎn)動(dòng)態(tài)變化 無(wú)需重新處理
例子:
document.getElementById("div1").onclick = function(e){
e = e || window.event;
var curDom = e.target.id;
switch(curDom){
case "btn1":
console.log("這是按鈕1");
break;
case "btn2":
console.log("這是按鈕2");
break;
case "btn3":
console.log("這是按鈕3");
break;
default:
break;}}}
11、原型鏈:原型通過(guò)繼承關(guān)系鏈接到一起,組成的鏈型結(jié)構(gòu),叫做原型鏈。
原型是函數(shù)prototype屬性對(duì)應(yīng)的對(duì)象,而多個(gè)構(gòu)造函數(shù)相互繼承,將彼此的原型對(duì)象進(jìn)行關(guān)聯(lián),組成了一條鏈型結(jié)構(gòu)。
12、匿名函數(shù):沒有名字的函數(shù)。通常不使用函數(shù)名調(diào)用此類函數(shù)。
13、自執(zhí)行函數(shù):匿名自執(zhí)行函數(shù),在函數(shù)內(nèi)部創(chuàng)建了一個(gè)獨(dú)立的命名空間,空間聲明變量不會(huì)對(duì)外部作用域產(chǎn)生污染。外部不會(huì)干擾影響內(nèi)部空間。
七、寫在結(jié)尾:
歸納整理的不夠全面,有待完善。
期待js初級(jí)程序設(shè)計(jì)出爐!