文章目錄
- 61.new的原理是什么?通過new的方式創建物件和通過字面量創建有什么區別?
- 62.prototype 和 proto 區別是什么?
- 63.使用ES5實作一個繼承?
- 64.取陣列的最大值(ES5、ES6)
- 65.ES6新的特性有哪些?
- 66.promise 有幾種狀態, Promise 有什么優缺點 ?
- 67.Promise建構式是同步還是異步執行,then呢 ?promise如何實作then處理 ?
- 68.Promise和setTimeout的區別 ?
- 69.如何實作 Promise.all ?
- 70.如何實作 Promise.finally ?
- 71.如何判斷img加載完成
- 72.如何阻止冒泡?
- 73.如何阻止默認事件?
- 74.ajax請求時,如何解釋json資料
- 75.json和jsonp的區別?
- 76.如何用原生js給一個按鈕系結兩個onclick事件?
- 77.拖拽會用到哪些事件
- 78.document.write和innerHTML的區別
- 79.jQuery的事件委托方法bind 、live、delegate、on之間有什么區別?
- (1)、bind 【jQuery 1.3之前】
- (2)、live 【jQuery 1.3之后】
- (3)、delegate 【jQuery 1.4.2中引入】
- (4)、on 【1.7版本整合了之前的三種方式的新事件系結機制】
- 80.瀏覽器是如何渲染頁面的?
- 81.$(document).ready()方法和window.onload有什么區別?
- 82. jquery中 . g e t ( ) 提 交 和 .get()提交和 .get()提交和.post()提交有區別嗎?
- 83.對前端路由的理解?前后端路由的區別?
- 84.手寫一個類的繼承
- 85.XMLHttpRequest:XMLHttpRequest.readyState;狀態碼的意思
- 86.請重寫Array 原型的map方法
- 先看一下map的用法
- 87.js編程題
- 1.請寫出代碼的運行結果?如何改進?
- //輸出結果為(五個5)
- 改進
- 2.請寫出列印結果,并解釋為什么?
- 3.請寫出列印結果,并解釋為什么?
61.new的原理是什么?通過new的方式創建物件和通過字面量創建有什么區別?
new:
- 創建一個新物件,
- 這個新物件會被執行[[原型]]連接,
- 將建構式的作用域賦值給新物件,即this指向這個新物件.
- 如果函式沒有回傳其他物件,那么new運算式中的函式呼叫會自動回傳這個新物件,
function new(func) {
lat target = {};
target.__proto__ = func.prototype;
let res = func.call(target);
if (typeof(res) == "object" || typeof(res) == "function") {
return res;
}
return target;
}
字面量創建物件,不會呼叫 Object建構式, 簡潔且性能更好;
new Object() 方式創建物件本質上是方法呼叫,涉及到在proto鏈中遍歷該方法,當找到該方法后,又會生產方法呼叫必須的 堆疊資訊,方法呼叫結束后,還要釋放該堆疊,性能不如字面量的方式,
通過物件字面量定義物件時,不會呼叫Object建構式,
62.prototype 和 proto 區別是什么?
prototype是建構式的屬性,
__proto__是每個實體都有的屬性,可以訪問 [[prototype]] 屬性,
實體的__proto__與其建構式的prototype指向的是同一個物件,
function Student(name) {
this.name = name;
}
Student.prototype.setAge = function(){
this.age=20;
}
let Jack = new Student('jack');
console.log(Jack.__proto__);
//console.log(Object.getPrototypeOf(Jack));;
console.log(Student.prototype);
console.log(Jack.__proto__ === Student.prototype);//true
63.使用ES5實作一個繼承?
組合繼承(最常用的繼承方式)
function SuperType() {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
SuperType.prototype.sayName = function() {
console.log(this.name);
}
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
console.log(this.age);
}
64.取陣列的最大值(ES5、ES6)
// ES5 的寫法
Math.max.apply(null, [14, 3, 77, 30]);
// ES6 的寫法
Math.max(...[14, 3, 77, 30]);
// reduce
[14,3,77,30].reduce((accumulator, currentValue)=>{
return accumulator = accumulator > currentValue ? accumulator : currentValue
});
65.ES6新的特性有哪些?
- 新增了塊級作用域(let,const)
- 提供了定義類的語法糖(class)
- 新增了一種基本資料型別(Symbol)
- 新增了變數的解構賦值
- 函式引數允許設定默認值,引入了rest引數,新增了箭頭函式
- 陣列新增了一些API,如 isArray / from / of 方法;陣列實體新增了 entries(),keys() 和 values() 等方法
- 物件和陣列新增了擴展運算子
- ES6 新增了模塊化(import/export)
- ES6 新增了 Set 和 Map 資料結構
- ES6 原生提供 Proxy 建構式,用來生成 Proxy 實體
- ES6 新增了生成器(Generator)和遍歷器(Iterator)
66.promise 有幾種狀態, Promise 有什么優缺點 ?
promise有三種狀態: fulfilled, rejected, pending.
Promise 的優點:
- 一旦狀態改變,就不會再變,任何時候都可以得到這個結果
- 可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回呼函式
Promise 的缺點:
- 無法取消 Promise
- 當處于pending狀態時,無法得知目前進展到哪一個階段
67.Promise建構式是同步還是異步執行,then呢 ?promise如何實作then處理 ?
Promise的建構式是同步執行的,then 是異步執行的,
68.Promise和setTimeout的區別 ?
Promise 是微任務,setTimeout 是宏任務,同一個事件回圈中,promise.then總是先于 setTimeout 執行,
69.如何實作 Promise.all ?
要實作 Promise.all,首先我們需要知道 Promise.all 的功能:
- 如果傳入的引數是一個空的可迭代物件,那么此promise物件回呼完成(resolve),只有此情況,是同步執行的,其它都是異步回傳的,
- 如果傳入的引數不包含任何 promise,則回傳一個異步完成.
promises 中所有的promise都“完成”時或引數中不包含 promise 時回呼完成,
- 如果引數中有一個promise失敗,那么Promise.all回傳的promise物件失敗
- 在任何情況下,Promise.all 回傳的 promise 的完成狀態的結果都是一個陣列
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
let index = 0;
let result = [];
if (promises.length === 0) {
resolve(result);
} else {
setTimeout(() => {
function processValue(i, data) {
result[i] = data;
if (++index === promises.length) {
resolve(result);
}
}
for (let i = 0; i < promises.length; i++) {
//promises[i] 可能是普通值
Promise.resolve(promises[i]).then((data) => {
processValue(i, data);
}, (err) => {
reject(err);
return;
});
}
})
}
});
}
70.如何實作 Promise.finally ?
不管成功還是失敗,都會走到finally中,并且finally之后,還可以繼續then,并且會將值原封不動的傳遞給后面的then.
Promise.prototype.finally = function (callback) {
return this.then((value) => {
return Promise.resolve(callback()).then(() => {
return value;
});
}, (err) => {
return Promise.resolve(callback()).then(() => {
throw err;
});
});
}
71.如何判斷img加載完成
一、load事件
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>img - load event</title>
</head>
<body>
<img id="img1" src="http://pic1.win4000.com/wallpaper/f/51c3bb99a21ea.jpgheight: 1em; vertical-align: -0.25em;">(“ul”").live...可以,但(“body”).find(“ul”).live…不行;
實體如下:$( document ).on( “click”, “#members li a”, function( e ) {} );
(3)、delegate 【jQuery 1.4.2中引入】
定義和用法:將監聽事件系結在就近的父級元素上
語法:delegate(selector,type,[data],fn)
特點:
(1)、選擇就近的父級元素,因為事件可以更快的冒泡上去,能夠在第一時間進行處理,
(2)、更精確的小范圍使用事件代理,性能優于.live(),可以用在動態添加的元素上,
實體如下:
$("#info_table").delegate(“td”,“click”,function(){/顯示更多資訊/});
$(“table”).find("#info").delegate(“td”,“click”,function(){/顯示更多資訊/});
(4)、on 【1.7版本整合了之前的三種方式的新事件系結機制】
定義和用法:將監聽事件系結到指定元素上,
語法:on(type,[selector],[data],fn)
實體如下:$("#info_table").on(“click”,“td”,function(){/顯示更多資訊/});引數的位置寫法與delegate不一樣,
說明:on方法是當前JQuery推薦使用的事件系結方法,附加只運行一次就洗掉函式的方法是one(),
總結 :.bind(), .live(), .delegate(),.on()分別對應的相反事件為:.unbind(),.die(), .undelegate(),.off()
80.瀏覽器是如何渲染頁面的?
渲染的流程如下:
1.決議HTML檔案,創建DOM樹,
自上而下,遇到任何樣式(link、style)與腳本(script)都會阻塞(外部樣式不阻塞后續外部腳本的加載),
2.決議CSS,優先級:瀏覽器默認設定<用戶設定<外部樣式<行內樣式<HTML中的style樣式;
3.將CSS與DOM合并,構建渲染樹(Render Tree)
4.布局和繪制,重繪(repaint)和重排(reflow)
81.$(document).ready()方法和window.onload有什么區別?
(1)、window.onload方法是在網頁中所有的元素(包括元素的所有關聯檔案)完全加載到瀏覽器后才執行的,
(2)、$(document).ready() 方法可以在DOM載入就緒時就對其進行操縱,并呼叫執行系結的函式,
82. jquery中
.
g
e
t
(
)
提
交
和
.get()提交和
.get()提交和.post()提交有區別嗎?
相同點:都是異步請求的方式來獲取服務端的資料;
異同點:
1、請求方式不同:
.
g
e
t
(
)
方
法
使
用
G
E
T
方
法
來
進
行
異
步
請
求
的
,
.get() 方法使用GET方法來進行異步請求的,
.get()方法使用GET方法來進行異步請求的,.post() 方法使用POST方法來進行異步請求的,
2、引數傳遞方式不同:get請求會將引數跟在URL后進行傳遞,而POST請求則是作為HTTP訊息的物體內容發送給Web服務器的,這種傳遞是對用戶不可見的,
3、資料傳輸大小不同:get方式傳輸的資料大小不能超過2KB 而POST要大的多
4、安全問題: GET 方式請求的資料會被瀏覽器快取起來,因此有安全問題,
83.對前端路由的理解?前后端路由的區別?
前端的路由和后端的路由在實作技術上不一樣,但是原理都是一樣的,在 HTML5 的 history API 出現之前,前端的路由都是通過 hash 來實作的,hash 能兼容低版本的瀏覽器,
http://10.0.0.1/
http://10.0.0.1/#/about
http://10.0.0.1/#/concat
服務端路由:每跳轉到不同的URL,都是重新訪問服務端,然后服務端回傳頁面,頁面也可以是服務端獲取資料,然后和模板組合,回傳HTML,也可以是直接回傳模板HTML,然后由前端JS再去請求資料,使用前端模板和資料進行組合,生成想要的HTML,
前端路由:每跳轉到不同的URL都是使用前端的錨點路由,實際上只是JS根據URL來操作DOM元素,根據每個頁面需要的去服務端請求資料,回傳資料后和模板進行組合,當然模板有可能是請求服務端回傳的,這就是 SPA 單頁程式,
在js可以通過window.location.hash讀取到路徑加以決議之后就可以回應不同路徑的邏輯處理,
history 是 HTML5 才有的新 API,可以用來操作瀏覽器的 session history (會話歷史),基于 history 來實作的路由可以和最初的例子中提到的路徑規則一樣,
H5還新增了一個hashchange事件,也是很有用途的一個新事件:
當頁面hash(#)變化時,即會觸發hashchange,錨點Hash起到引導瀏覽器將這次記錄推入歷史記錄堆疊頂的作用,window.location物件處理“#”的改變并不會重新加載頁面,而是將之當成新頁面,放入歷史堆疊里,并且,當前進或者后退或者觸發hashchange事件時,我們可以在對應的事件處理函式中注冊ajax等操作!
但是hashchange這個事件不是每個瀏覽器都有,低級瀏覽器需要用輪詢檢測URL是否在變化,來檢測錨點的變化,當錨點內容(location.hash)被操作時,如果錨點內容發生改變瀏覽器才會將其放入歷史堆疊中,如果錨點內容沒發生變化,歷史堆疊并不會增加,并且也不會觸發hashchange事件,
84.手寫一個類的繼承
繼承的形式有很多中,js高程里面歸納了其中,我簡單說一下前三種,
1.原型繼承
function Parent(){
this.name = "parent";
}
Parent.prototype.getName = function(){
return this.name;
}
function Child(){
this.name = "child";
}
//繼承parent
Child.prototype = new Parent();
2.建構式繼承
function Animal(name){
this.name = name;
this.eat = function(){
consoel.log(this.name + "吃飯");
}
}
var cat = new Animal("maomi");
cat.name;
cat.eat();
85.XMLHttpRequest:XMLHttpRequest.readyState;狀態碼的意思
XmlHttpRequest(Ajax)狀態碼readyState
當一個XMLHttpRequest初次創建時,這個屬性的值是從0開始,知道接收完整的HTTP回應,這個值增加到4,有五種狀態:
狀態0 (請求未初始化): (XMLHttpRequest)物件已經創建或已被abort()方法重置,但還沒有呼叫open()方法;
狀態1 (載入服務器連接已建立):已經呼叫open() 方法,但是send()方法未呼叫,尚未發送請求;
狀態2 (載入完成,請求已接收): send()方法已呼叫,HTTP請求已發送到web服務器,請求已經發送完成,未接收到回應;
狀態3 (互動,請求處理中):所有回應頭部都已經接收到,回應體開始接收但未完成,即可以接收到部分回應資料;
狀態4 (請求完成,且相應已就緒):已經接收到了全部資料,并且連接已經關閉,
86.請重寫Array 原型的map方法
先看一下map的用法
//語法:array.map(function(currentValue,index,arr), thisValue)
//用法:
var arr = [1,2,3,4];
arr.map((item,index,arr) => {
return item*10 //新陣列為10,20,30,40
})
//map遍歷陣列,回傳一個新陣列,不改變原陣列的值,
用js實作
Array.prototype.fakeMap = function(fn,context) {
let arr = this;
let temp = [];
for(let i=0;i<arr.length;i++){
let result = fn.call(context,arr[i],i,arr);
temp.push(result);
}
return temp;
}
87.js編程題
1.請寫出代碼的運行結果?如何改進?
請寫出代碼運行結果?如何改進?
for(var i=0;i<5;i++){
setTimeout(function(){
console.log(i)
},1000)
}
//輸出結果為(五個5)
原因是:
settimeout是異步執行,1s后往任務佇列里面添加一個任務,
只有主線上的全部執行完,才會執行任務佇列里的任務,
當主線執行完成后,i是5,所以此時再去執行任務佇列里的任務時,i全部是5了,
改進
for(let i=0;i<5;i++){
setTimeout(function(){
console.log(i)
},1000)
}
//輸出 0,1,2,3,4
決議:
for回圈頭部的let不僅將i系結到for回圈塊中,
它也將其重新系結到 **回圈體的每一次迭代** 中,確保上一次迭代結束的值重新被賦值,
setTimeout里面的function()屬于一個新的域,
通過 var 定義的變數是無法傳入到這個函式執行域中的,
而通過使用 let 來宣告塊變數,這時候變數就能作用于這個塊,
所以 function就能使用 i 這個變數了;
2.請寫出列印結果,并解釋為什么?
請寫出代碼運行結果,并解釋為什么?
let length = 10;
function fn(){
console.log(this.length);
}
var obj = {
length:5,
method:function(){
return fn;
}
}
obj.method()();
//輸出結果:0
決議:
“this永遠指向呼叫他的物件”,在執行obj.method()方法時,如果函式內部有this,則this確實是指向obj,但是method()內部執行的是fn()函式,而fn()函式系結的物件是window,即window.fn()
所以this指的事window
但是為什么沒有顯示10而是顯示的0是因為
let宣告變數會形成塊級作用域,且不存在宣告提升,而var存在宣告提升,所以當使用let宣告變數時,不存在宣告提升,length屬性實際上并沒有添加到window物件中,
3.請寫出列印結果,并解釋為什么?
請寫出代碼運行結果,并解釋為什么?
var name = "clobal";
var object = {
name:'local',
fn:function(){
return this.name;
},
getName:function(){
alert("1." + this.name);
return function(){
return this.name;
}
},
getFn:function(){
return this.fn;
}
};
var fun = object.getName();
alert("2."+fun());
alert("3."+fun.apply(object));
alert("4."+fun.call(object));
var fn = object.getFn();
alert("5."+fn())
輸出結果
1.local 2.clocal 3.local 4.local 5.clocal
決議
this物件是在運行時基于函式的執行環境系結的,
匿名函式的執行環境具有全域性,
因此匿名函式的this指向window
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/215374.html
標籤:其他
上一篇:axios 默認配置和實體配置
