函數(shù)
JavaScript中的函數(shù)通過function進行聲明养筒,一個函數(shù)可以有return語句也可以沒有试躏。
函數(shù)的參數(shù)與其他語言有所不同,可以隨意傳進參數(shù)棠枉,不管參數(shù)個數(shù)或者數(shù)據(jù)類型浓体。
函數(shù)體內(nèi)可通過arguments對象訪問參數(shù),其使用類似數(shù)組辈讶。
因為其沒有函數(shù)簽名(接受的參數(shù)類型和數(shù)量)命浴,所以沒有重載,若定義了兩個相同的函數(shù)贱除,則該函數(shù)名屬于后面的函數(shù)生闲。
但是可以通過arguments來模仿函數(shù)的重載
<script>
function sayHi(){
if(arguments.length==0)
return "Hi";
if(arguments.length==1)
return arguments[0];
if(arguments.length==2)
return "hello"+arguments[1];
}
</script>
rest參數(shù)
由于js中傳進來的參數(shù)可以有多個,所以ES6引進了rest參數(shù)月幌,它的用法如下
var pig=function(a,b,...rest){
console.log(a);
console.log(b);
console.log(rest);
}
pig(1,2,3,4,5);//a=1 b=2 Array[3,4,5]
若參數(shù)數(shù)量不夠碍讯,rest為空數(shù)組。
由于js巨大的設計失誤扯躺,this的指向變幻莫測捉兴,所以ECMA引入了apply與call來控制this的指向。
apply接收兩個參數(shù)录语,第一個參數(shù)就是要綁定的this變量轴术,第二個參數(shù)是Array,表示函數(shù)本身的參數(shù)钦无。call與apply類似逗栽,只不過apply將參數(shù)以數(shù)組形式打包傳入,call按順序一個個傳入失暂。
function getAge(){
var y=new Date().getFullYear();
return y-this.birth;
}
var years={
birth:2000,
age:getAge
}
console.log(getAge());//NaN
console.log(getAge.apply(years,[]));//18
高階函數(shù)
一個函數(shù)接受另一個函數(shù)作為其參數(shù)彼宠,那么它就是高階函數(shù)
var i=function(x,y,f){
return f(x)+f(y);
}
var j=i(-2,1,Math.abs);
console.log(j);//3
map/reduce
map()方法定義在js的Array對象中,調(diào)用某一個Array的map方法弟塞,會返回一個新的Array凭峡。
function pow(x){
return x*x;
}
var arr=[1,2,3,4,5];
console.log(arr.map(pow));
reduce也是同樣,但是傳入的函數(shù)必須要有兩個參數(shù)决记,reduce()把算出來的結(jié)果與下一個元素做累計計算摧冀。
fliter
fliter可以將arr中的某些元素過濾掉,返回剩下的元素。filter也傳入一個函數(shù)索昂,根據(jù)函數(shù)返回時true還是false決定元素是否保留建车。
var arr=[1,2,3,4,5];
console.log(arr.filter(function(x){
return x%2!==0;
}))//刪除偶數(shù)
排序
sort的排序非常坑爹椒惨,它通過ASCII碼進行排序缤至,如果是數(shù)字的話,會先將其轉(zhuǎn)換為字符串康谆,由于'1'的ASCII小于'2'所以'10'排在'2'前面领斥。
但是sort()方法本身也是一個高階函數(shù),可以通過接收一個比較函數(shù)實現(xiàn)正確的排序
arr.sort(function(x,y){
if(x>y)
return 1;
if(x<y)
return -1;
return 0;
})
閉包
當函數(shù)不需要立即計算時沃暗,可以使用閉包月洛,
閉包即在函數(shù)中定義另外一個函數(shù),這個函數(shù)可以引用外部函數(shù)的參數(shù)和變量孽锥,這樣的函數(shù)就叫做閉包膊存。
但是閉包中不要引用任何循環(huán)變量,或者后續(xù)會發(fā)生變化的變量忱叭。
箭頭函數(shù)
箭頭函數(shù)相當于匿名函數(shù)隔崎,只包含一個表達式時可以省掉return,包含多個表達式時不可省掉return韵丑。爵卒,如果參數(shù)大于一個,要用()括起來撵彻,(x,y)=>{....}
并且箭頭函數(shù)修復了this的指向钓株,this總是指向詞法作用域。
x=>x*x
相當于
function(x){
return x*x;
}
變量
變量有基本類型和引用類型兩種
基本類型有 Undefined,Null,Boolean,Number,String五種
這五種類型是按值訪問的陌僵,可以操作保存在變量值中實際的值
但是引用類型為內(nèi)存中的對象轴合,但是js不允許直接操作內(nèi)存,
所以操作對象是按引用訪問的碗短,對引用類型的值受葛,我們可以操作其屬性和方法
<script>
var person=new Object();
person.name="IDLER";
</script>
除了上述不同,它們在復制的時候也有不同
例如:
var name="IDLER";
var me=name;
name和me兩個變量是相互獨立的
但是對于引用類型,這兩個變量其實是相互關(guān)聯(lián)的偎谁,
相當于me是一個指向name的指針总滩,
而name是指向它存的值的指針。
var name=new Object();
var me=name;
但是函數(shù)的參數(shù)傳遞只能按值傳遞巡雨,類似c語言中的形參闰渔。形參只是函數(shù)內(nèi)的局部變量。但是若傳入的是一個對象铐望,對其修改仍然會改變實參冈涧,因為即使是形參也指向的是同一片內(nèi)存茂附。但若在函數(shù)內(nèi)改變了形參的指向,其就無效了
function setName(obj){
obj.name="abc";
obj=new Object();
obj.name="sufei";
}
最終輸出結(jié)果obj.name還是abc督弓。
檢測類型
可以用typeof檢測變量的類型营曼,但是不管是對象還是null,其返回的都是object咽筋。
其語法為 變量 instanceof constructor
若用其檢測基本類型,返回結(jié)果永遠為false
person instanceof Object;
colors instanceof Array;
執(zhí)行環(huán)境
全局環(huán)境是最外圍的環(huán)境徊件,在Web瀏覽器中奸攻,執(zhí)行環(huán)境是window對象,所有全局變量和函數(shù)都是作為window的屬性和方法創(chuàng)建的虱痕。同樣的睹耐,每個函數(shù)都有它的執(zhí)行環(huán)境。當變量在一個環(huán)境中執(zhí)行的時候部翘,會產(chǎn)生一個作用域鏈硝训,每個作用域鏈的前端永遠都是當前的執(zhí)行環(huán)境,函數(shù)最開始只包含一個變量arguments新思,作用域的下一個對象來自外部環(huán)境窖梁,再下一個變量來自下一個外部環(huán)境,這樣一直延續(xù)到全局環(huán)境夹囚。
var color="blue";
function change(){
color="red"
function rechange(){
var newcolor="pink";
newcolor=color;
}
rechange();
}
change();
rechange()中包含三個變量對象纵刘,即自身的變量對象,change()的變量對象荸哟,以及全局的變量對象假哎。若外部對象與內(nèi)部對象重名,由于作用域的查找是由內(nèi)到外鞍历,所以內(nèi)部的變量會屏蔽外部的變量舵抹。
由于for循環(huán)中的var定義的不是具有局部作用域的對象,所以ES6新增了let劣砍。
for(let i=0;i<1000;i++){
.......
}
i+=1//undefined
ES6新增了const關(guān)鍵字定義常量惧蛹,const定義的變量也具有塊級作用域。
ES6新特性:Map和Set
Map
js中的{}對象可以表達其他語言中的Map或是字典的數(shù)據(jù)結(jié)構(gòu)刑枝,即一組鍵值對赊淑,但是{}中的鍵必須偽字符串,為了解決這個問題仅讽,ES6新增了Map
初始化Map需要用一個二維數(shù)組
var m=new Map([['IDLER',1],['yuan',2]]);
m.get('IDLER');//1
Map中還有set方法可以對其初始化,delete方法刪除某一對鍵值陶缺。
m.set('pig',3);
m.delete('pig');
Set
Set是一組鍵的集合践盼,但是不包含對應的value夯到,并且沒有重復的key
var s=new Set([1,2,3,4,5]);
s.add(5);
s.delete(4);
//s{1,2,3,5}
iterable
由于Map和Set不能像數(shù)組一樣用下標進行遍歷,ES6引入新類型iterable,其包含Array,Map载慈,Set三種類型,都可以通過for...of...進行循環(huán)
var s=new Set([1,2,3,4,5]);
var m=new Map([['yuan',1],['zhou',2]]);
var x=[1,2,3,4,5];
for(var i of s){
console.log(i);
}
for(var j of m){
console.log(j[0]+":"+j[1]);
}
for(var k of x){
console.log(k);
}
ES6新特性:解構(gòu)賦值
var [x,y]=[1,'pig'];
面向?qū)ο缶幊?/h2>
js與其他語言的面向?qū)ο蟛惶粯由环眩洳粎^(qū)分類和實例的概念汤锨,而是通過原型實現(xiàn)面向?qū)ο缶幊獭?/p>
var Student = {
name: 'Robot',
height: 1.2,
run: function () {
console.log(this.name + ' is running...');
}
};
var xiaoming = {
name: '小明'
};
xiaoming.__proto__ = Student;
最后一行將xiaoming這個對象的原型指向了Student對象,于是實現(xiàn)了方法和屬性的繼承百框,此時闲礼,如果將xiaoming這個對象的原型指向另一個對象比如bird,它就失去了Student中含有的方法和屬性.
此時小明變成了一只鳥铐维,不能跑柬泽,只能飛
var Bird = {
fly: function () {
console.log(this.name + ' is flying...');
}
};
xiaoming.__proto__ = Bird;
另一種方法是使用Object.create()方法
Object.create()方法可以傳入一個原型對象,并創(chuàng)建一個基于該原型的新對象嫁蛇,但是新對象什么屬性都沒有锨并,因此,我們可以編寫一個函數(shù)來創(chuàng)建xiaoming
function createStudent(name) {
// 基于Student原型創(chuàng)建一個新對象:
var s = Object.create(Student);
// 初始化新對象:
s.name = name;
return s;
}
若使用obj.xxx,js會先從該對象上查找該屬性睬棚,找不到就到它的原型上找第煮,直到上溯到Object.prototype,如果還沒有找到就返回undefined抑党。
以下摘自廖雪峰的博客:
例如包警,創(chuàng)建一個Array對象:
var arr = [1, 2, 3];
其原型鏈是:
arr ----> Array.prototype ----> Object.prototype ----> null
Array.prototype定義了indexOf()、shift()等方法底靠,因此你可以在所有的Array對象上直接調(diào)用這些方法揽趾。
當我們創(chuàng)建一個函數(shù)時:
function foo() {
return 0;
}
函數(shù)也是一個對象,它的原型鏈是:
foo ----> Function.prototype ----> Object.prototype ----> null
由于Function.prototype定義了apply()等方法苛骨,因此篱瞎,所有函數(shù)都可以調(diào)用apply()方法。
很容易想到痒芝,如果原型鏈很長俐筋,那么訪問一個對象的屬性就會因為花更多的時間查找而變得更慢,因此要注意不要把原型鏈搞得太長严衬。
js中除了用{}直接創(chuàng)建一個對象澄者,還可以通過構(gòu)造函數(shù)創(chuàng)建一個對象
function Student(){...}
var xiaoming=new Student();
此時原型鏈為xiaoming ----> Student.prototype ----> Object.prototype ----> null
也就是說新創(chuàng)建的對象xiaoming的原型鏈指向Student的原型鏈
同時xiaoming還獲得了一個constructor屬性,指向Student對象
原型繼承
JavaScript的原型繼承實現(xiàn)方式就是:
1.定義新的構(gòu)造函數(shù)请琳,并在內(nèi)部用call()調(diào)用希望“繼承”的構(gòu)造函數(shù)粱挡,并綁定this;
2.借助中間函數(shù)F實現(xiàn)原型鏈繼承俄精,最好通過封裝的inherits函數(shù)完成询筏;
3.繼續(xù)在新的構(gòu)造函數(shù)的原型上定義新方法。
class繼承
ES6中正式引用了class
如果用新的class關(guān)鍵字來編寫Student竖慧,可以這樣寫:
class Student {
constructor(name) {
this.name = name;
}
hello() {
alert('Hello, ' + this.name + '!');
}
}
class中包含構(gòu)造函數(shù)和定義在原型對象上的函數(shù)hello()
所以現(xiàn)在可以直接使用extends實現(xiàn)繼承嫌套,調(diào)用父類的構(gòu)造方法要在前面加上super
class PrimaryStudent extends Student {
constructor(name, grade) {
super(name); // 記得用super調(diào)用父類的構(gòu)造方法!
this.grade = grade;
}
myGrade() {
alert('I am at grade ' + this.grade);
}
}
如何編寫原生AJAX
步驟:1.new一個XMLHttpRequest()對象
2.監(jiān)聽Http的相應結(jié)果和狀態(tài)碼
3.如果成功就調(diào)用open方法和send方法逆屡,open方法兩個參數(shù),一個是提交方式(get/post)踱讨,一個是打開的文件路徑魏蔗。send方法用來send一些數(shù)據(jù)
function success(text) {
var textarea = document.getElementById('test-response-text');
textarea.value = text;
}
function fail(code) {
var textarea = document.getElementById('test-response-text');
textarea.value = 'Error code: ' + code;
}
var request = new XMLHttpRequest(); // 新建XMLHttpRequest對象
request.onreadystatechange = function () { // 狀態(tài)發(fā)生變化時,函數(shù)被回調(diào)
if (request.readyState === 4) { // 成功完成
// 判斷響應結(jié)果:
if (request.status === 200) {
// 成功痹筛,通過responseText拿到響應的文本:
return success(request.responseText);
} else {
// 失敗莺治,根據(jù)響應碼判斷失敗原因:
return fail(request.status);
}
} else {
// HTTP請求還在繼續(xù)...
}
}
// 發(fā)送請求:
request.open('GET', '/api/categories');
request.send();
準備面試的一些提問:
1.HTML
一.遇到script標簽時瀏覽器的行為
(1.不帶async,defer標簽:阻值文檔渲染帚稠,直到腳本加載完畢
(2.帶async屬性
由腳本插入的script標簽默認是async的谣旁。對內(nèi)聯(lián)腳本設置async屬性是沒有意義的,也不產(chǎn)生其他效果翁锡。其包含的腳本總是立即執(zhí)行的蔓挖。
(3.帶defer屬性
推遲腳本執(zhí)行夕土,不阻止文檔解析
defer屬性是會確保腳本在文檔解析完畢后執(zhí)行的——即使這個腳本在文檔解析過程中就已經(jīng)下載完畢變成可執(zhí)行的狀態(tài)馆衔,瀏覽器也會推遲這個腳本的執(zhí)行,直到文檔解析完畢怨绣,并在DOMContentLoaded之前角溃。
二.遇到link標簽瀏覽器的行為
link標簽也會阻塞文檔的渲染
<link>標簽的rel屬性
rel屬性是<link>標簽的核心屬性,利用rel屬性篮撑,搜索引擎可以獲取更多有關(guān)鏈接的信息减细。
三.href和src的區(qū)別
和你這么說吧,href 表示超文本引用(hypertext reference)赢笨,在 link和a 等元素上使用未蝌。src 表示來源地址,在 img茧妒、script萧吠、iframe 等元素上。
src 的內(nèi)容桐筏,是頁面必不可少的一部分纸型,是引入。href 的內(nèi)容梅忌,是與該頁面有關(guān)聯(lián)狰腌,是引用。區(qū)別就是牧氮,引入和引用琼腔。
四.meta標簽的作用
供機器解讀,告訴機器如何解析這個頁面
還有一個用途是可以添加服務器發(fā)送到瀏覽器的http頭部內(nèi)容踱葛,例如我們?yōu)轫撁嬷刑砑尤缦耺eta標簽:
<meta http-equiv="charset" content="iso-8859-1">
<meta http-equiv="expires" content="31 Dec 2008">
meta標簽中還有charset的可選屬性<meta charset="utf-8">
五.onload函數(shù)的作用
頁面加載完后立即執(zhí)行的函數(shù)
1展姐、當 onload
事件觸發(fā)時躁垛,頁面上所有的DOM,樣式表圾笨,腳本教馆,圖片,flash都已經(jīng)加載完成了擂达。
2土铺、當 DOMContentLoaded
事件觸發(fā)時,僅當DOM加載完成板鬓,不包括樣式表悲敷,圖片,flash俭令。
DOMContentLoaded機制更加合理后德,因為我們可以容忍圖片,flash延遲加載抄腔,卻不可以容忍看見內(nèi)容后頁面不可交互瓢湃。
2.CSS
一.行級元素與塊級元素的區(qū)別與聯(lián)系
行級元素與塊級元素可以轉(zhuǎn)換
display:inline display:block
行級元素占一整行,不會自動換行
塊級元素獨占一行赫蛇,塊級元素想要在一行绵患,必須設置浮動
行級元素上下margin,padding無效
塊級元素內(nèi)可以包含行級和塊級元素
行級元素中只能包含行級元素悟耘。
二.如何實現(xiàn)垂直水平居中
margin: 0 auto;是最好的居中方法
水平垂直居中方法:margin-top,margin-left各50%落蝙,然后減去自身寬高。
父元素position:relative 子元素position:absolute
如果寬高未知暂幼,可改為:transform: translate(-50%,-50%);
三.position的屬性和意義
position中的屬性有top,left,right,bottom
absolute:絕對定位相對第一個父元素進行定位
fixed:生成絕對定位,相對于瀏覽器窗口進行定位
relative:相對定位
static:沒有定位
inherit:從父元素繼承定位
四.z-index的作用
z-index相當于網(wǎng)頁的z軸筏勒,當定位的元素重疊時,越在上面的元素越優(yōu)先顯示
五.vertical-align的作用
設置元素垂直對齊的方式
六.什么是盒模型旺嬉?
盒模型的組成大家肯定都懂管行,由里向外content,padding,border,margin.
3.JavaScript
一.基本類型和引用類型的區(qū)別
基本數(shù)據(jù)類型:按值訪問,可操作保存在變量中的實際的值鹰服〔⊥基本類型值指的是簡單的數(shù)據(jù)段。
基本數(shù)據(jù)類型有這五種:Undefined悲酷、Null套菜、String、Number设易、Boolean逗柴。
引用類型:當復制保存著對象的某個變量時,操作的是對象的引用顿肺,但在為對象添加屬性時戏溺,操作的是實際的對象渣蜗。引用類型值指那些可能為多個值構(gòu)成的對象。
引用類型有這幾種:object旷祸、Array耕拷、RegExp、Date托享、Function骚烧、特殊的基本包裝類型(String、Number闰围、Boolean)以及單體內(nèi)置對象(Global赃绊、Math)。
① 引用類型值可添加屬性和方法羡榴,而基本類型值則不可以碧查。
② 在復制變量值時,基本類型會在變量對象上創(chuàng)建一個新值校仑,再復制給新變量忠售。此后,兩個變量的任何操作都不會影響到對方肤视;而引用類型是將存儲在變量對象的值復制一份給新變量档痪,但是兩個變量的值都指向存儲在堆中的一個對象涉枫,也就是說邢滑,其實他們引用了同一個對象,改變其中一個變量就會影響到另一個變量愿汰。
typeof:確定變量是字符串困后、數(shù)值、布爾值還是undefined的最佳工具衬廷。
instanceof :判斷是否是某個對象類型摇予。
二.cookie,session
cookie在客戶端吗跋,session在服務器端
localstroage和sessionstorage都保存在客戶端侧戴,sessionstorage會話期間可用,localstorage只有不清除跌宛,理論上一直可用酗宋,后兩者有易用的原生接口