什麼是面向對象?javascript
程序中的事物都是用對象結構來描述的,全部的程序都是用面向對象的思想,管理數據和功能的。css
面向對象三大特色:封裝 繼承 多態html
什麼是封裝?前端
建立一個對象結構,用來保存一個事物的屬性和方法(功能) java
有幾種封裝方式? 3種 jquery
01 用{ }建立 ,var obj={ }es6
02 用new建立, var obj=new Obj( )web
03 用構造函數------建立多個對象面試
什麼是繼承?ajax
父對象的成員,子對象無需重複建立,就可直接使用
繼承能夠減小代碼的重用,節約內存
何時用繼承?
多個子對象,都擁有相同的方法要定義時,就要用到繼承。 將方法保存在父對象中,全部的子對象均可以用。
如何實踐繼承?
js中都是自動繼承原型對象的
什麼是多態?
一個函數在不一樣狀況下表現出不一樣的狀態
什麼是重寫?
若是子對象以爲從父對象繼承來的成員很差用,可在子對象建立同名成員,覆蓋父對象中的成員。使用時只要本身有,就先用本身的。
關於閉包?
什麼是? 閉包是函數和函數做用域的結合
閉包既能夠重用變量,又能夠防止變量不會被全局污染
閉包的造成?
內層函數引用着外層函數的局部變量,致使外層函數的局部變量在調用後不能釋放
閉包的使用場景有哪些?什麼狀況下會想到用閉包?
給一個函數綁定一個專屬的變量,好比說: 通常在寫js的時候,會先寫一個匿名函數自調來避免全局污染。
使用局部變量來實現反覆使用的效果,爲何局部變量能夠反覆使用?————由於造成了閉包
私有化數據
閉包有啥問題? 有可能致使棧溢出
做用域?
js有兩級做用域,一個是全局做用域,一個是局部做用域。
全局做用域:在全局做用域下聲明的變量,能夠在任何合法位置訪問。
局部做用域:在函數內部聲明的變量,只能在函數內部訪問
做用域鏈?
什麼是?由多級做用域組成的鏈式結構,當函數被調用的時候,函數會將本身全部用到的做用域串聯起來。
做用域鏈,串聯着當前函數可使用的全部做用域範圍,保存着當前函數可用的全部變量
做用域鏈還控制着變量的使用順序:先局部,後全局。
什麼是實例?
一個函數是經過構造函數new出來的,就說這個對象是構造函數的實例。
在js中,new出來的實例 ,默承認以訪問本身構造函數原型對象上的任何屬性。
什麼是原型對象?
原型對象說的是prototype,全部函數一旦建立出來,瀏覽器就會分配一個原型對象給這個函數,函數經過prototype屬性能夠找到本身的原型對象,而且構造函數的實例默承認以訪問到構造函數對應的原型。
什麼是原型對象: 在一個類型的你們庭中,集中保存全部子對象共用數據的父對象
爲何要使用原型對象?
由於用構成函數new出來的實例,每次都會建立一次方法,每new一次,就建立一次。這樣會形成內存浪費。
雖然能夠將構造函數中的方法寫到外邊,能夠避免每次new都會重複建立,可是這種方法可能會形成全局污染或者函數覆蓋
使用原型對象將方法放到原型對象中,就能夠以解決浪費內存的問題了。
原型對象身上的屬性: contructor 找到本身的函數
瀏覽器爲了咱們的學習和工做方便,幫咱們實現了一個屬性,這個屬性能夠看到實例對應的是哪一個原型對象
實例的屬性: _ _proto_ _ 非標準屬性,不建議在生產環境下使用
什麼是原型鏈?
由多級原型對象,逐級繼承,造成的鏈式結構 。 保存着當前對象全部可用的屬性和方法
從實例開始,實例默承認以訪問到本身構造函數的原型,這個原型也是其餘構造函數的實例,也能夠訪問本身構造函數的原型。
實例 和 原型以及 原型和原型 之間的關係,咱們稱之爲原型鏈。
總結:
01 每一個函數(類)都有一個prototype(原型)屬性,屬性值是一個對象;這個對象中存儲了當前類供實例調取使用的公有屬性和方法
02 在‘瀏覽器默認’給原型開闢的堆內存中有一個屬性constructor; 儲存的是當前類自己(默認開闢的堆內存有constructor屬性,本身建立的原型對象中沒有)
03 每個對象(實例)都有一個__proto__屬性,這個屬性指向當前實例所屬類的原型(不肯定所屬的類,都指向 Oject.prototype)
在實際項目基於面向對象開發的時候(構造原型設計模式),咱們根據須要,不少時候會重定向類的原型(讓類的原型指向本身開闢的堆內存)
存在的問題:01 本身開闢的堆內存中沒有constructor屬性,致使類的原型構造函數缺失(解決:本身手動在堆內存中增長constructor屬性)
02 當原型重定向後,瀏覽器默認開闢的那個原型堆內存會被釋放掉,若是以前已經存儲了一些方法或者屬性,這些東西都會丟失(因此:
內置類的原型不容許重定向到本身開闢的堆內存,由於內置類原型上自帶不少屬性和方法,重定向後都沒了,這樣是不被容許的)
對象查找屬性的規則?
先在本身身上找,若是有,直接使用,若是沒有,順着原型鏈往上找,找不到就繼續往上找,若是找到了null都沒有的話,就返回undefined;
自定義構造函數
批量的建立對象
當js中 ,new關鍵字和函數配合使用時,就必定會建立出一個新的對象 ----規定
一個函數是否是構造函數取決於它的用途,不取決於它的首字母是否是大寫,也不取決於它的裏面有沒有this;
爲何要用構造函數來建立對象?爲了批量建立具備相同屬性,相同方法的對象
function Fn(name,age){ this.name=name this.age = age } var p=new Fn('zm',20) //總結:專門用來建立對象,而且和new關鍵字配合使用的時候,纔是構造函數; //構造函數必定是函數,函數不必定是構造函數
this的指向問題
01 this老是指向函數的直接調用者 ,若是有new關鍵子,this指向new出來的實例對象
02 普通函數的this默認指向window
03 當一個函數被保存爲對象的一個方法時,誰調用這個函數this就指向誰
1 obj.fun() fun()中的this 指的是 .前的obj
2 fun() fun()中的this 默認指 window
window.fun()
3 new fun() 中的this-> 強行指向正在建立的新對象
4 Array.prototype.sum=function(){this->未來調用sum的 .前的任意數組對象!}
call()後面的參數要用字符串一個一個傳入, applay()後面的參數要在一個 數組中; bind()返回的是改變this指向後的函數,不會當即執行,apply()和call()會當即執行。
// call() 第一個參數是要綁定給this的值,後邊傳入的是參數列表。當第一個參數爲null和undefined的時候,this默認指向window。 getName.call(obj, 'Dot', 'Dolby')
// apply() 的用法和call()同樣,可是傳參方式不同 。多個參數須要傳入時,apply要用數組傳參
getName.apply(obj, ['Dot', 'Dolby'])
// bind() 方法不會當即執行,而是返回一個改變了this指向的函數,須要var 一個變量來接收。
關於瀏覽器的兼容問題?
如今的瀏覽器幾乎都是使用webkit gecko trident內核,因此兼容這三個幾乎就能夠知足了。
webkit : Chrome Safari (蘋果瀏覽器) Google
gecko :Firefox(火狐)
trident: IE
360瀏覽器、獵豹瀏覽器內核:IE+Chrome雙內核;
搜狗、遨遊、QQ瀏覽器內核:Trident(兼容模式)+Webkit(高速模式);
百度瀏覽器、:IE內核;
三、IE6雙邊問題,塊狀元素float後,又添加了橫向的margin,在IE6下比設置的值要大(屬於雙倍浮動的bug)
解決方案:給float標籤添加display:inline,將其轉換爲行內元素
02 事件處理中很是有用的event屬性得到亦不相同,標準瀏覽器是做爲參數帶入,而ie是window.event方式得到,得到目標元素ie爲e.srcElement 標準瀏覽器爲e.target
03 ie中是不能操做tr的innerHtml的
css HACK
CSS屬性Hack、CSS選擇符Hack以及IE條件註釋Hack, Hack主要針對IE瀏覽器。
一、屬性級Hack:好比IE6能識別下劃線「_
」和星號「*
」,IE7能識別星號「*
」,但不能識別下劃線」_
」,而firefox兩個都不能認識。
二、選擇符級Hack:好比IE6能識別*html .class{}
,IE7能識別*+html .class{}
或者*:first-child+html .class{}
。
三、IE條件註釋Hack:IE條件註釋是微軟IE5開始就提供的一種非標準邏輯語句。好比針對全部IE:<!-[if IE]><!-您的代碼-><![endif]>
,針對IE6及如下版本:<!-[if it IE 7]><!-您的代碼-><![endif]->
,這類Hack不只對CSS生效,對寫在判斷語句裏面的全部代碼都會生效。
PS:條件註釋只有在IE瀏覽器下才能執行,這個代碼在非IE瀏覽下被當作註釋視而不見。能夠經過IE條件註釋載入不一樣的CSS、JS、HTML和服務器代碼等。
渲染樹和dom樹的區別?
渲染樹是由DOM樹和CSS樣式規則組成的, DOM樹+CSS樣式=渲染樹
DOM樹只有html結構,沒有樣式
渲染樹可以識別樣式,渲染樹中每一個節點都有本身的style,可是渲染樹不包含隱藏的節點和head節點 如:display:none;
渲染引擎的工做原理?
01 解析html創建DOM樹:瀏覽器把獲取的html代碼,解析成一個DOM樹,HTML中每一個標籤都是DOM樹中的一個節點
01 CSS樣式規則: 瀏覽器把全部樣式(用戶定義的CSS和用戶代理)解析成**樣式規則**
02 構建渲染樹: DOM樹和樣式規則組合成 渲染樹 render tree
03 佈局渲染樹:計算每一個元素的大小,位置給每一個節點分配屏幕上精確的座標
04 繪製渲染樹:遍歷渲染樹,對每一個節點進行繪製
解析dom樹,dom樹和css樣式規則組成渲染樹, 而後瀏覽器會佈局渲染樹,最後瀏覽器繪製渲染樹;
多核瀏覽器?
多核瀏覽器,指的是瀏覽器擁有多個渲染引擎。
多個渲染引擎並不能同時工做提升渲染效率。
多核的目的,只是爲了處理兼容性問題。
什麼是進程?什麼是線程?
進程是系統中正在運行的一個程序,程序一旦運行就是進程。
一個程序至少有一個進程,一個進程至少有一個線程.
一個進程能夠有多個線程
常見的瀏覽器內核有哪些?
Trident 內核: IE 360 搜狗
gecko 內核: 火狐瀏覽器
webkit 內核: safari(蘋果的瀏覽器) Chrome(Blink,webkit的分支)
iframe有哪些缺點
iframe會阻塞頁面的Onload事件,(阻塞頁面加載,讓網頁顯示變慢),iframe不是並行加載
使用iframe,css和js都須要額外引入,給頁面帶來額外的請求次數。
使用iframe不利於搜索優化(SEO)
優勢:程序調入靜態頁面比較方便;
在頁面中引入公共的頁頭 方法?
iframe引入,雖然方便,可是它不是並行加載的,會阻塞頁面的onload事件,致使網頁變慢。而且若是使用iframe還須要額外引入css和js代碼。
ajax().then( repalce(header) ) 引入, 異步加載。
如何實現瀏覽器內多個標籤頁之間的通訊?
想要實現瀏覽器內多標籤之間的通訊,可使用 cookie或者localstorage,它們都是瀏覽器存儲數據的容器,而且能夠多頁面共享。
cookie的獲取方式: document.cookie
localstorage的使用方式:
(1) 設置:localStorage.setItem(key , value)
(2) 獲取:localStorage.getItem( key )
也可使用webSocket,前端使用簡單方便,可是須要服務端的配合,它能夠實現實時通訊,而且是雙向通訊,瀏覽器和服務器能夠相互發送以及接收請求
事件委託,事件代理
分爲三個階段: 捕獲階段 目標階段 冒泡階段
優勢: 減小代碼 節約內存
原理: 事件流 事件委託/事件冒泡
阻止事件默認行爲和事件冒泡
e.preventDefault() 阻止事件默認行爲
e.stopPropagation() 阻止事件冒泡
return false等效於同時調用e.preventDefault()和e.stopPropagation()
jsonp和ajax有什麼關係?
沒有半毛錢關係
jsonp原理? 強調 後端 返回一個函數調用
前端動態建立scriipt標籤,藉助script標籤發送跨域請求。
後端返回一個函數調用,將數據放到函數調用參數中返回。
跨域資源共享? cors
將返回的響應頭中的ip地址,設置爲當前網頁的地址,就能夠進行跨域了
在不知道要轉換的值是否是null或undefined的狀況下,還可使用String()函數,它可以將任何類型的值轉換爲字符串。
jQuery中$的做用?
01 $(' 選擇器 ') 建立jquery對象,並查找元素,封裝進jquery對象中------ 其實就是 查找
02 $(' DOM元素 ') 如:$(this) $(e.target) $(txt), 將dom元素封裝爲jquery對象,就可調用jquery家的簡化版函數
由於dom元素不能直接調用jquery家的函數 ,因此$(this),將dom元素封裝爲jquery對象
03 $( `html片斷` ) 建立jquery對象,同時建立dom元素 === document.createElement("li")
04 $(function(){ ... }) 綁定事件,在DOM內容加載後自動觸發
ES中內置對象:有幾個?
11個, Number String Boolean
Arry Date RegExp Math Error( try{...}catch( ){...})
throw Error('錯誤提示')
function Object
global(瀏覽器中被window代替)
1 function Mobile(name, price){ 2 this.name = name; 3 this.price = price; 4 } 5 Mobile.prototype.sell = function(){ 6 alert(this.name + ",售價 $" + this.price); 7 } 8 var iPhone7 = new Mobile("iPhone7", 1000); 9 iPhone7.sell();
02 es6 class
class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } } var point = new Point(2, 3);
爲何要繼承? 少寫代碼
方法一 拷貝繼承 利用? for(var key in obj) 瞭解 (對象和對象的繼承)
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>Document</title>
8 </head>
9 <body>
10 <!-- js屬性對象的hasOwnProperty方法 11 obj.hasOwnProperty()用來判斷對象自身屬性是否存在,若是有true,沒有false 12 -->
13
14 <script>
15 var zh={ 16 wife:'yy', 17 money:999999999999, 18 houses:['一棟樓','二棟樓','三棟樓'] 19 } 20
21 var zxh={ 22 wife:['FF'] 23 } 24 // 對象和對象之間的繼承
25 // 拷貝繼承
26 for(var key in zh){//key表示對象的屬性名
27 if(!zxh.hasOwnProperty(key)){//判斷若是本身有,就不用繼承了
28 zxh[key]=zh[key] 29 } 30
31 } 32 console.log(zxh) 33 // 輸出結果: {wife: Array(1), money: 999999999999, houses: Array(3)}
34 // houses: (3) ["一棟樓", "二棟樓", "三棟樓"]
35 // money: 999999999999
36 // wife: ["FF"]
37 </script>
38 </body>
39 </html>
方法二 ?var 新對象 = Object.create(被繼承的對象 ) 繼承 (對象和對象的繼承)
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>Document</title>
8 </head>
9 <body>
10 <!-- 對象和對象之間的繼承 11 Object.create()繼承 -->
12 <script>
13 var zh={ 14 wife:'yy', 15 money:999999999999, 16 houses:['一棟樓','二棟樓','三棟樓'] 17 } 18
19 var zxh = Object.create(zh) 20 zxh.wife=['fff','FFF'] 21 console.log(zxh) 22 console.log(zxh.money) // 999999999999
23 console.log(zxh.houses) // ["一棟樓", "二棟樓", "三棟樓"]
24 console.log(zxh.wife) // ["fff", "FFF"]
25
26 </script>
27 </body>
28 </html>
方法三 構造函數的繼承 (構造函數和構造函數的繼承)
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>Document</title>
8 </head>
9 <body>
10 <!-- 當咱們須要批量建立對象的時候,須要用到構造函數,構造函數如何繼承? -->
11 <!-- 借用構造函數法繼承 -->
12 <!-- student裏面的name age不想在重複的書寫了 -->
13 <script>
14 function Person (name,age){//03 'zh',18
15 this.name=name; // a.name='zh'
16 this.age=age; // a.age=18
17 } 18
19 function Student (name,age,score){//('zh',18,100)
20 Person.call(this,name,age);//02 this指向a, Person.call()調用了函數,並將參數'zh',18傳入
21 this.score=score; 22
23 } 24
25 var a=new Student('zh',18,100) //01 new Student()會調用Student構造函數,而且將構造函數中的this指向new出來的新對象a,
26 console.log(a) //還會把參數('zh',18,100)傳入 構造函數中
27
28 // new的做用
29 // 建立一片空的儲存空間(建立一個新的對象)
30 // 讓子對象繼承父對象
31 // 調用構造函數,並將構造函數中的this 指向new新對象
32 // 返回新對象的地址給變量
33
34
35 </script>
36 </body>
37 </html>
組合繼承 = 借用構造函數 + 原型繼承
<script>
function Person (name,age){ this.name=name; this.age=age; } Person.prototype.say=function(){ console.log('你好我是'+this.name) } function Student (name,age,score){ Person.call(this,name,age); this.score=score; } // 若是想要繼承原型上的屬性,那麼就要使用原型繼承這個方式
// 原型繼承: 專門用來繼承寫在原型上的屬性的
Student.prototype=new Person(); // 改變原型鏈的指向
var a=new Student('zh',18,100) console.log(a) // 屬性寫在構造函數中, 方法寫在原型上 // 私有屬性寫在構造函數中,共有的屬性寫在原型上 // 借用構造函數法用來繼承私有屬性, 原型繼承用來繼承共有的屬性 // 組合繼承 = 借用構造函數 + 原型繼承 // Student.prototype = Person.prototype; 會致使共同使用同一個原型鏈,在繼承函數中修改原型,被繼承的函數也會修改 // Student.prototype=new Person();
</script>
js繼承?
單個對象之間的繼承:
拷貝繼承利用for key in
新對象 =Object.create(被繼承的對象)
構造函數之間的繼承:
借用構造函數繼承,利用 call()和 new 的配合 實現,借用構造函數繼承,只能繼承寫在函數體內this.xxx的屬性,不能繼承原型對象上的方法
function Person ( name,age ){
this.name=name;
this.age=age
}
function Student( name,age,money){
Person.call(this,name,age)
this.money=money
}
DOM的瀏覽器兼容性問題:
普通事件模型:DOM的3個階段:01 外向內 捕獲 02 目標觸發 03 內向外: 冒泡
IE8 只有兩個階段 : 目標觸發 冒泡(內向外的)
標準 :elem.addEventListener('事件名', function( ){ } , false); 第三個參數是false表示冒泡階段觸發 若是是true表示捕獲階段觸發
IE8 : element.attachEvent('on + 事件名', function( ) { });
標準 elem.addEventListener('事件名', function( e ){ e} , false)
IE8 不會自動傳入事件對象e 。 IE8的事件對象保存在 window.event 中
elem.attachEvent('事件名', function( ){ window.event } )
得到目標元素?
標準 e.target
IE8 e.srcElement
阻止冒泡?:
標準DOM:e.stopPropagation( );
IE8 : e.cancelBubble=true;
阻止默認行爲?:
標準DOM:e.preventDefault( );
IE8 : return false;
target 只會出如今事件流的目標階段
currentTarget 可能出如今事件流的任何階段
當事件流處在目標階段時,兩者的指向相同
instanceof做用:
對象 instanceof 函數:
js高級:判斷函數的原型是否在對象的原型鏈上。若是是返回ture, 不然,返回false;
原型鏈不可變的問題:
一旦實例被建立出來以後,他的原型鏈就固定了,不會隨着函數原型的變化而變化
上下文調用模式:
call 會調用函數
applay 會調用函數,第二個參數傳數組[ ]
bind 不會調用函數,克隆一個新的函數
new的指向
當棧裏面的代碼執行完畢了,事件輪詢就會把任務隊列中的第一個拿到棧中執行,執行完畢以後,事件輪詢還會去任務隊列中拿下一個,再放到棧中執行。
斐波那契 和 遞歸 ?
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--斐波那契數列: 1 1 2 3 5 8 13-->
<script>
// 求斐波那契數列中第n個數字是幾 // function fn(n){ // if(n == 1 || n == 2){ // return 1; // } // // return fn(n - 1) + fn(n - 2); // // } // // console.log(fn(6));
function fn(i){ console.log(i++); if(i == 10000){ return; } fn(i); } fn(0); // 遞歸: 函數中本身調用了本身 // 注意: 若是要寫遞歸,必須給一個出口,若是沒有會形成棧溢出 // 棧溢出: 棧裏面放不下了就會溢出
// (function(){//這個不是遞歸,是函數的自調用 // // })(); //自調用函數,不是遞歸 把申明函數和調用函數合成了一步 //
// (function fn(){ // fn() // 是 遞歸 // })();
</script>
</body>
</html>
閉包面試題
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
<li>第1個li</li>
<li>第2個li</li>
<li>第3個li</li>
<li>第4個li</li>
<li>第5個li</li>
<li>第6個li</li>
</ul>
<script>
//不能使用this, 利用閉包,打印每個li的文本
var lis = document.getElementsByTagName('li'); // for(var i = 0; i < lis.length; i++) { // lis[i].onclick = function(){ //// console.log(this.innerText); // console.log(lis[i].innerText); // } // }
for(var i = 0; i < lis.length; i++) { (function(i){ lis[i].onclick = function(){ // console.log(this.innerText);
console.log(lis[i].innerText); } })(i); } </script>
</body>
</html>
問題 :圖片更換 html不刷新
須要上傳圖片預覽.可是第二次上傳圖片顯示的時候發現以前的圖片沒有改變.後通過分析發現是地址相同第二次改變img src屬性的時候圖片未發生改變,瀏覽器第二次不會去請求服務器。
今天在作ajax上傳圖片時:因爲新上傳的圖片會處理成和原來的圖片名稱同樣,這樣就形成img標籤的src看起來是沒有變化的,全部就不會從新請求圖片。
解決方案很easy:
在修改img的src屬性的時候加上一個隨機數便可,讓瀏覽器覺得每次請求的服務都不一樣.
加一個隨機數
image.attr('src', data.message+'?'+Math.random());
或者加一個時間戳
eval() 函數可計算某個字符串,並執行其中的的 JavaScript 代碼。
什麼是回調函數?
把一個函數做爲值,傳遞給形參。這種機制就叫作回到函數
function fn ( callback ){
}
fn( function (){ } )
知識點
事件綁定是異步編程,當觸發點擊行爲,綁定的方法執行的時候,外層循環已經結束;方法執行產生私有做用域,用到變量i,不是私有變量,按照做用域鏈的查找機制,找到的是全局下的i(此時全局的i已經成爲循環最後一次的結果)