冒泡:
1.event.stopPropagation();
事件處理過程中,阻止了事件冒泡,但不會阻擊默認行爲(它就執行了超鏈接的跳轉)
2.return false;
事件處理過程中,阻止了事件冒泡,也阻止了默認行爲(比如剛纔它就沒有執行超鏈接的跳轉)
還有一種有冒泡有關的:
3.event.preventDefault();
如果把它放在頭部A標籤的click事件中,點擊“點擊我”。
會發現它依次彈出:我是最裏層---->我是中間層---->我是最外層,但最後卻沒有跳轉到百度
它的作用是:事件處理過程中,不阻擊事件冒泡,但阻擊默認行爲(它只執行所有彈框,卻沒有執行超鏈接跳轉)
創建對象:
1.new 對象
var person = new Object();
person.name = "lisi";
person.age = 21;
person.family = ["lida","lier","wangwu"];
person.say = function(){
alert(this.name);
}
2.直接創建
var person ={
name: "lisi",
age: 21,
family: ["lida","lier","wangwu"],
say: function(){
alert(this.name);
}
};
3.工廠模式
function createPerson(name,age,family) {
var o = new Object();
o.name = name;
o.age = age;
o.family = family;
o.say = function(){
alert(this.name);
}
return o;
}
var person1 = createPerson("lisi",21,["lida","lier","wangwu"]); //instanceof無法判斷它是誰的實例,只能判斷他是對象,構造函數都可以判斷出
var person2 = createPerson("wangwu",18,["lida","lier","lisi"]);
console.log(person1 instanceof Object); //true
4.構造函數
function Person(name,age,family) {
this.name = name;
this.age = age;
this.family = family;
this.say = function(){
alert(this.name);
}
}
var person1 = new Person("lisi",21,["lida","lier","wangwu"]);
var person2 = new Person("lisi",21,["lida","lier","lisi"]);
console.log(person1 instanceof Object); //true
console.log(person1 instanceof Person); //true
console.log(person2 instanceof Object); //true
console.log(person2 instanceof Person); //true
console.log(person1.constructor); //constructor 屬性返回對創建此對象的數組、函數的引用
5.原型模式
function Person() {
}
Person.prototype.name = "lisi";
Person.prototype.age = 21;
Person.prototype.family = ["lida","lier","wangwu"];
Person.prototype.say = function(){
alert(this.name);
};
console.log(Person.prototype); //Object{name: 'lisi', age: 21, family: Array[3]}
var person1 = new Person(); //創建一個實例person1
console.log(person1.name); //lisi
var person2 = new Person(); //創建實例person2
person2.name = "wangwu";
person2.family = ["lida","lier","lisi"];
console.log(person2); //Person {name: "wangwu", family: Array[3]}
// console.log(person2.prototype.name); //報錯
console.log(person2.age); //21
6.混合模式
function Person(name,age,family){
this.name = name;
this.age = age;
this.family = family;
}
Person.prototype = {
constructor: Person, //每個函數都有prototype屬性,指向該函數原型對象,原型對象都有constructor屬性,這是一個指向prototype屬性所在函數的指針
say: function(){
alert(this.name);
}
}
var person1 = new Person("lisi",21,["lida","lier","wangwu"]);
console.log(person1);
var person2 = new Person("wangwu",21,["lida","lier","lisi"]);
console.log(person2);
事件穿透:
fastclick
是不是數組:
arr instanceof Array
arr.length
arr.constructor === Array
Object.prototype.toString.call(arr) === '[object Array]'
深拷貝淺拷貝:
淺拷貝:直接複製
深拷貝:JSON.parse() JSON.stringify()
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判斷ojb子元素是否爲對象,如果是,遞歸複製
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,簡單複製
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
閉包:
使用閉包的注意點
(1)由於閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致內存泄露。解決方法是,在退出函數之前,將不使用的局部變量全部刪除。
(2)閉包會在父函數外部,改變父函數內部變量的值。所以,如果你把父函數當作對象(object)使用,把閉包當作它的公用方法(Public Method),把內部變量當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數內部變量的值。
Ajax 請求過程:
(1)創建`XMLHttpRequest`對象,也就是創建一個異步調用對象.
(2)創建一個新的`HTTP`請求,並指定該`HTTP`請求的方法、`URL`及驗證信息.
(3)設置響應`HTTP`請求狀態變化的函數.
(4)發送`HTTP`請求.
(5)獲取異步調用返回的數據.
(6)使用JavaScript和DOM實現局部刷新.
跨域:(https://segmentfault.com/a/1190000015597029)
跨域原因:同源策略
解決辦法 1.jsonp 2.ifream 3.cors(請求頭) 4.代理
typeof返回值:
string || number|| undefined || boolean || function|| object
js的原始數據類型有哪些?
string , boolean , number , null , undefined
箭頭函數和普通函數有什麼區別?
1.箭頭函數沒有綁定this指針,普通函數的this指向調用函數的對象(匿名函數的this都指向全局window對象);
2.箭頭函數沒有構造器
數組去重:
1.創建新數組 原數組遍歷放入如果有重複則不放入
function uniq(array){
var temp = []; //一個新的臨時數組
for(var i = 0; i < array.length; i++){
if(temp.indexOf(array[i]) == -1){
temp.push(array[i]);
}
}
return temp;
}
2.對象鍵值法去重
function uniq(array){
var temp = {}, r = [], len = array.length, val, type;
for (var i = 0; i < len; i++) {
val = array[i];
type = typeof val;
if (!temp[val]) {
temp[val] = [type];
r.push(val);
} else if (temp[val].indexOf(type) < 0) {
temp[val].push(type);
r.push(val);
}
}
return r;
}
3. 排序後相鄰去除法
function uniq(array){
array.sort();
var temp=[array[0]];
for(var i = 1; i < array.length; i++){
if( array[i] !== temp[temp.length-1]){
temp.push(array[i]);
}
}
return temp;
}
4.數組下標法
function uniq(array){
var temp = [];
for(var i = 0; i < array.length; i++) {
//如果當前數組的第i項在當前數組中第一次出現的位置是i,才存入數組;否則代表是重複的
if(array.indexOf(array[i]) == i){
temp.push(array[i])
}
}
return temp;
}
5
function uniq(array){
var temp = [];
var index = [];
var l = array.length;
for(var i = 0; i < l; i++) {
for(var j = i + 1; j < l; j++){
if (array[i] === array[j]){
i++;
j = i;
}
}
temp.push(array[i]);
index.push(i);
}
console.log(index);
return temp;
}
6.new set()
var items = new Set([1, 2, 4, 4, 5]);
var array = Array.from(items);
console.log(array) // (4) [1, 2, 4, 5]
檢測一個對象是否有prop屬性,沒有就拋出異常,有的話返回true,並刪掉該屬性:
var o = {
age:10,
prop:"prop"
}
function hasProperty(pro,obj){
if(obj.hasOwnProperty(pro)){
delete obj.prop;
}else{
throw new Error("沒有該屬性");
}
}
hasProperty("prop",o)
console.log(o)
attr()和prop()的區別?
attr是自己定義屬性 prop 是修改元素固有屬性(checked、disabled ...)
touch和click有何區別?
touch有延遲等待雙擊事件
Vue的雙向綁定原理是什麼?
defineProperty
webpack原理是什麼?
合併腳本 (require)
get 和 post區別:
(1)post更安全(不會作爲url的一部分,不會被緩存、保存在服務器日誌、以及瀏覽器瀏覽記錄中)
(2)post發送的數據更大(get有url長度限制)
(3)post能發送更多的數據類型(get只能發送ASCII字符)
(4)post比get慢
(5)post用於修改和寫入數據,get一般用於搜索排序和篩選之類的操作(淘寶,支付寶的搜索查詢都是get提交),目的是資源的獲取,讀取數據
但是在服務器端 get請求更安全,不會修改數據
爲什麼get比post更快
1.post請求包含更多的請求頭
因爲post需要在請求的body部分包含數據,所以會多了幾個數據描述部分的首部字段(如:content-type),這其實是微乎其微的。
2.最重要的一條,post在真正接收數據之前會先將請求頭髮送給服務器進行確認,然後才真正發送數據
post請求的過程:
(1)瀏覽器請求tcp連接(第一次握手)
(2)服務器答應進行tcp連接(第二次握手)
(3)瀏覽器確認,併發送post請求頭(第三次握手,這個報文比較小,所以http會在此時進行第一次數據發送)
(4)服務器返回100 Continue響應
(5)瀏覽器發送數據
(6)服務器返回200 OK響應
get請求的過程:
(1)瀏覽器請求tcp連接(第一次握手)
(2)服務器答應進行tcp連接(第二次握手)
(3)瀏覽器確認,併發送get請求頭和數據(第三次握手,這個報文比較小,所以http會在此時進行第一次數據發送)
(4)服務器返回200 OK響應
也就是說,目測get的總耗是post的2/3左右,這個口說無憑,網上已經有網友進行過測試。
3.get會將數據緩存起來,而post不會
可以做個簡短的測試,使用ajax採用get方式請求靜態數據(比如html頁面,圖片)的時候,如果兩次傳輸的數據相同,第二次以後消耗的時間將會在10ms以內(chrome測試),而post每次消耗的時間都差不多。經測試,chrome和firefox下如果檢測到get請求的是靜態資源,則會緩存,如果是數據,則不會緩存,但是IE什麼都會緩存起來,當然,應該沒有人用post去獲取靜態數據吧,反正我是沒見過。
4.post不能進行管道化傳輸
http權威指南中是這樣說的:http的一次會話需要先建立tcp連接(大部分是tcp,但是其他安全協議也是可以的),然後才能通信,如果 每次連接都只進行一次http會話,那這個連接過程佔的比例太大了!於是出現了持久連接:在http/1.0+中是connection首部中添加keep-alive值,在http/1.1中是在connection首部中添加persistent值,當然兩者不僅僅是命名上的差別,http/1.1中,持久連接是默認的,除非顯示在connection中添加close,否則持久連接不會關閉,而http/1.0+中則恰好相反,除非顯示在connection首部中添加keep-alive,否則在接收數據包後連接就斷開了。
出現了持久連接還不夠,在http/1.1中,還有一種稱爲管道通信的方式進行速度優化:把需要發送到服務器上的所有請求放到輸出隊列中,在第一個請求發送出去後,不等到收到服務器的應答,第二個請求緊接着就發送出去,但是這樣的方式有一個問題:不安全,如果一個管道中有10個連接,在發送出9個後,突然服務器告訴你,連接關閉了,此時客戶端即使收到了前9個請求的答覆,也會將這9個請求的內容清空,也就是說,白忙活了……此時,客戶端的這9個請求需要重新發送。這對於冪等請求還好(比如get,多發送幾次都沒關係,每次都是相同的結果),如果是post這樣的非冪等請求(比如支付的時候,多發送幾次就慘了),肯定是行不通的。
所以,post請求不能通過管道的方式進行通信!很有可能,post請求需要重新建立連接,這個過程不跟完全沒優化的時候一樣了麼?所以,在可以使用get請求通信的時候,不要使用post請求,這樣用戶體驗會更好,當然,如果有安全性要求的話,post會更好。管道化傳輸在瀏覽器端的實現還需考證,貌似默認情況下大部分瀏覽器(除了opera)是不進行管道化傳輸的,除非手動開啓!
get 傳參長度原因是由於瀏覽器本身原因
完整的HTTP請求過程(https://blog.csdn.net/u014600626/article/details/78720763)
1.域名解析(DNS解析)
2.發起TCP的3次握手
3.建立TCP連接後發起http請求
4.服務器端響應http請求,瀏覽器得到html代碼
5.瀏覽器解析html代碼,並請求html代碼中的資源
6.瀏覽器對頁面進行渲染呈現給用戶