1法瑟, BFC是什么剩彬?觸發(fā)BFC的條件是什么?觸發(fā)后又能解決什么問題呢
- BFC是什么弹惦?
形成一個(gè)完全獨(dú)立的空間否淤,讓空間里的子元素不會(huì)影響到外面的布局。
塊格式化上下文是web頁(yè)面可視化css渲染的一部分棠隐,是塊盒子的布局過程發(fā)生的區(qū)域石抡,也是浮動(dòng)元素與其他元素交互的區(qū)域 - 如何觸發(fā) BFC
1,float不為none
2助泽,position不為relative和static
3啰扛,overflow為auto scroll和hidden
4,display值table-cell或 inline-block - 觸發(fā)之后又能解決什么問題呢
1嗡贺,解決浮動(dòng)元素令父元素高度坍塌的問題
這是因?yàn)楦?dòng)的子元素脫離了文檔流隐解,可以給父級(jí)添加overflow: hidden;或者display: table-cell或者display: flex;或display: inline-block;或者position: fixed或者position: absolute
如果處于布局需要可能無法給父元素設(shè)置這些屬性,常用的還有其他辦法: - 給父元素也加float: left
- 給父元素增加固定高度
- 在浮動(dòng)的子元素后面增加一個(gè)空元素诫睬,并設(shè)置{clear: both}來清除浮動(dòng)
-
為浮動(dòng)的最后一個(gè)子元素設(shè)置偽元素煞茫,::after{clear: both}
2,兩欄自適應(yīng)布局
比如左側(cè)固定,右側(cè)自適應(yīng)
方法1:
左邊左浮動(dòng),右邊設(shè)置margin-left: 200px
方法2:
父元素position: relative;
左邊position: absolute;top: 0;left: 0;bottom: 0; width: 200px;
右邊margin-left: 200px;
方法3:
左邊position: absolute;top: 0;left: 0;bottom: 0; width: 200px;
右邊左邊position: absolute;top: 0;right 0;left: 200px;width: 100%;
3蚓曼,外邊距垂直方向重合
方法1:
給其中一個(gè)p元素添加父元素,并給父元素添加overflow: hidden;
方法2:
用padding代替margin
2, 以下代碼輸出什么
var foo={n:1};
(function(foo){
console.log(foo.n);
foo.n=3;
var foo={n:2};
console.log(foo.n);
})(foo);
console.log(foo.n);
var foo = {n:1};
(function(foo){ //形參foo同實(shí)參foo一樣指向同一片內(nèi)存空間炸宵,這個(gè)空間里的n的值為1
var foo; //重復(fù)聲明辟躏,無效。
console.log(foo.n); //輸出1
foo.n = 3; //形參與實(shí)參foo指向的內(nèi)存空間里的n的值被改為3
foo = {n:2}; //形參foo指向了新的內(nèi)存空間土全,里面n的值為2.
console.log(foo.n); //輸出新的內(nèi)存空間的n的值
})(foo);
console.log(foo.n); //實(shí)參foo的指向還是原來的內(nèi)存空間捎琐,里面的n的值為3.
3,cookies , sessionStorage 和 localStorage 的區(qū)別
4,JS中的原型和原型鏈
創(chuàng)建的每一個(gè)函數(shù)都有一個(gè)prototype(原型)屬性裹匙,這個(gè)屬性是一個(gè)指針瑞凑,指向一個(gè)對(duì)象,而這個(gè)對(duì)象的用途就是包含可以由特定類型的所有實(shí)例共享的屬性和方法概页,簡(jiǎn)單點(diǎn)說就是籽御,當(dāng)我們創(chuàng)建函數(shù)的時(shí)候系統(tǒng)會(huì)自動(dòng)分配一個(gè)prototype屬性,用來存儲(chǔ)可以讓所有實(shí)例共享的屬性和方法
每一個(gè)構(gòu)造函數(shù)都有一個(gè)prototype屬性惰匙,這個(gè)屬性指向一個(gè)對(duì)象技掏,也就是原型對(duì)象
原型對(duì)象默認(rèn)擁有一個(gè)constructor屬性,指向指向他的那個(gè)構(gòu)造函數(shù)
每個(gè)對(duì)象都擁有一個(gè)隱藏的__proto__项鬼,指向他的原型對(duì)象
function Person() {}
var p = new Person()
p.__proto__ = Person.prototype // true
Person.prototype.constructor = Person // true
原型特點(diǎn):
function Person () {
}
Person.prototype.name = '小馬'
Person.prototype.age = 20
Person.prototype.sayHi = function () {
console.log('Hi')
}
var p1 = new Person()
var p2 = new Person()
p1.name = '小王'
p1.age = 18
console.log(p1.name) // '小王'
console.log(p1.age) // 18
console.log(p1.sayHi()) // Hi
console.log(p2.name) // '小馬'
console.log(p2.age) // 20
console.log(p2.sayHi()) // Hi
從代碼中可以看出:
- 實(shí)例可以共享原型上的屬性和方法
- 實(shí)例自身的屬性和方法會(huì)屏幕原型上的屬性和方法哑梳,實(shí)例上沒有的會(huì)去原型上找
以上代碼可以寫為:
function Person () {
}
Person.prototype = {
name: '小馬',
age: 20,
sayHi () {
console.log('Hi')
}
}
var p1 = new Person()
var p2 = new Person()
p1.name = '小王'
p1.age = 18
console.log(p1.name) // '小王'
console.log(p1.age) // 18
console.log(p1.sayHi()) // Hi
console.log(p2.name) // '小馬'
console.log(p2.age) // 20
console.log(p2.sayHi()) // Hi
只是在我們重寫原型鏈的時(shí)候需要注意以下問題 :
function Person () {}
var p = new Person ()
Person.prototype = {
name: '小王',
age: 20
}
console.log(Person.prototype.constructor == Person) // false
console.log(p.name) // undefined
重寫原型對(duì)象之前:
重寫原型對(duì)象之后:
- 在已經(jīng)創(chuàng)建了實(shí)例的情況下重寫原型,會(huì)切斷現(xiàn)有實(shí)例與新原型之間的聯(lián)系
- 重寫原型對(duì)象绘盟,會(huì)導(dǎo)致原型對(duì)象的constructor指向Object鸠真,導(dǎo)致原型鏈關(guān)系混亂
請(qǐng)看以下代碼:
var arr = [1,2,4]
console.dir(arr.valueOf())
arr.__proto__ === Array.prototype
true
Array.prototype.__proto__ === Object.prototype
true
arr.__proto__.__proto__ === Object.prototype
true
// 原型鏈的終點(diǎn)
Object.prototype.__proto__ === null
true
原型鏈如下:
arr ---> Array.prototype ---> Object.prototype ---> null
這就是傳說中的原型鏈,層層向上查找龄毡,最后還沒有就返回undefined
4,JavaScript 中的繼承
什么是繼承吠卷?
繼承是指一個(gè)對(duì)象直接使用另外一個(gè)對(duì)象的屬性和方法
由此可見只要實(shí)現(xiàn)屬性和方法的繼承,就達(dá)到繼承的效果
我們先創(chuàng)建一個(gè)Person類
function Person (name, age) {
this.name = name
this.age = age
}
// 方法定義在構(gòu)造函數(shù)的原型上
Person.prototype.getName = function () { console.log(this.name)}
此時(shí)我想創(chuàng)建一個(gè)Teacher類沦零,我希望它可以繼承Person所有的屬性祭隔,并且額外添加屬于自己特定的屬性
function Teacher (name, age, subject) {
Person.call(this, name, age)
this.subject = subject
}
屬性的繼承是通過在一個(gè)類內(nèi)執(zhí)行另外一個(gè)類的構(gòu)造函數(shù),通過call指定this為當(dāng)前執(zhí)行環(huán)境路操,這樣就可以得到另外一個(gè)類的所有屬性
function Person (name, age) {
this.name = name
this.age = age
}
Person.prototype.getName = function () {
console.log(this.name)
}
function Teacher (name,age,sub) {
Person.call(this,name, age)
this.sub = sub
}
var te = new Teacher('小王', 18, '前端')
console.log(te.age) // 18
console.log(te.name) // '小王'
很明顯Teacher成功繼承了Person的屬性
4, html5 本地存儲(chǔ)( localStorage )相關(guān) api 疾渴,并實(shí)現(xiàn) getAll 方法,獲取本地存儲(chǔ)
- setItem(key,value) 添加數(shù)據(jù)
- getItem(key) 根據(jù)key獲取值
- key(index) 根據(jù)索引獲取key
- removeItem(key) 根據(jù)key刪除一條數(shù)據(jù)
- clear() 清空數(shù)據(jù)
-
length:獲取總數(shù)據(jù)的長(zhǎng)度
getAll()這個(gè)方法我沒太明白想獲取什么寻拂,所以我采用了key()和getItem()方法結(jié)合獲取鍵值對(duì)
5, JS中substr與substring的區(qū)別
substr和substring都是截取字符串中子串程奠,非常相近,可以有一個(gè)或兩個(gè)參數(shù)
語(yǔ)法:substr(start [祭钉,length]) 第一個(gè)字符的索引是0瞄沙,start必選 length可選
substring(start [, end]) 第一個(gè)字符的索引是0,start必選 end可選
相同點(diǎn):當(dāng)有一個(gè)參數(shù)時(shí),兩者的功能是一樣的距境,返回從start指定的位置直到字符串結(jié)束的子串
var str = "hello Tony";
str.substr(6); //Tony
str.substring(6); //Tony
不同點(diǎn):有兩個(gè)參數(shù)時(shí)
(1)substr(start,length) 返回從start位置開始length長(zhǎng)度的子串
“goodboy”.substr(1,6); //oodboy
【注】當(dāng)length為0或者負(fù)數(shù)申尼,返回空字符串
(2)substring(start,end) 返回從start位置開始到end位置的子串(「不包含end」)
“goodboy”.substring(1,6); //oodbo
【注】:
(1)substring 方法使用 start 和 end 兩者中的較小值作為子字符串的起始點(diǎn)
(2)start 或 end 為 NaN 或者負(fù)數(shù),那么將其替換為0
str是字符串時(shí)str.substring(start,end)和str.slice(start,end)完全等價(jià)垫桂;str是數(shù)組時(shí)str.slice(start,end)還可以繼續(xù)用师幕,str.substring(start,end)就不行了。
6, JS 截取地址欄指定字符后的內(nèi)容
1,獲取地址欄路徑
var url = window.location.href;
2,截取指定字符后的內(nèi)容
/**
* 截取指定字符后的內(nèi)容
* @param url 路徑
* @param parameter 字符
*/
function getCaption(url,parameter) {
var index = url.lastIndexOf(parameter);
url = url.substring(index + 1, url.length);
return url;
}
3,調(diào)用方法及結(jié)果
var url="http://www.baidu.com?123";
var a = getCaption(url, "?");
// 123
7, 以下代碼的運(yùn)行結(jié)果是
var game='4399'
game.substring(2,1)
console.log(game)
// 4399
這里有兩個(gè)坑诬滩,第一個(gè)是start<stop的話霹粥,會(huì)自動(dòng)交換這兩個(gè)參數(shù),第二個(gè)是substring對(duì)原數(shù)組不會(huì)改變疼鸟。
8,JS的重定向有哪些
location.assign("http://www.baidu.com");
location.;
window.location="http://www.baidu.com";
top.location="http://www.baidu.com";
self.location="http://www.baidu.com";
window.location.;
9, 談?wù)勀銓?duì)虛擬DOM原理的理解
1,什么是Virtual DOM(虛擬DOM)
Virtual DOM是對(duì)DOM的抽象后控,本質(zhì)上是JavaScript對(duì)象,這個(gè)對(duì)象就是更加輕量級(jí)的對(duì)DOM的描述.
2,為什么需要Virtual DOM
既然我們已經(jīng)有了DOM,為什么還需要額外加一層抽象空镜?
首先浩淘,我們都知道在前端性能優(yōu)化的一個(gè)秘訣就是盡可能少地操作DOM,不僅僅是DOM相對(duì)較慢,更因?yàn)轭l繁變動(dòng)DOM會(huì)造成瀏覽器的回流或者重回吴攒,這些都是性能的殺手张抄,因此我們需要這一層抽象,在patch過程中盡可能地一次性將差異更新到DOM中洼怔,這樣保證了DOM不會(huì)出現(xiàn)性能很差的情況.
其次署惯,現(xiàn)代前端框架的一個(gè)基本要求就是無須手動(dòng)操作DOM,一方面是因?yàn)槭謩?dòng)操作DOM無法保證程序性能,多人協(xié)作的項(xiàng)目中如果review不嚴(yán)格茴厉,可能會(huì)有開發(fā)者寫出性能較低的代碼泽台,另一方面更重要的是省略手動(dòng)DOM操作可以大大提高開發(fā)效率.
最后什荣,也是Virtual DOM最初的目的矾缓,就是更好的跨平臺(tái),比如Node.js就沒有DOM,如果想實(shí)現(xiàn)SSR(服務(wù)端渲染),那么一個(gè)方式就是借助Virtual DOM,因?yàn)閂irtual DOM本身是JavaScript對(duì)象
10, 怎么利用img進(jìn)行xss攻擊
這個(gè)問題稻爬,我有點(diǎn)蒙蔽嗜闻,我以為是 轉(zhuǎn)發(fā)圖片給上當(dāng)者,然后就攻擊了桅锄,網(wǎng)上找了答案琉雳,果不其然,我想錯(cuò)了
因?yàn)樽罱趯W(xué)習(xí)web安全友瘤,出于好奇翠肘,嘗試對(duì)CSDN進(jìn)行了XSS注入,沒想到真的成功了辫秧。
操作步驟:
直接找一篇博客束倍,在底下評(píng)論
<img src="pic.gif" οnerrοr="javascript:this.src='/noPic.gif';" alt="pic" />
因?yàn)镃SDN做了簡(jiǎn)單的轉(zhuǎn)義,他會(huì)將注入的標(biāo)簽,去掉閉合性绪妹,也就是會(huì)把我注入的內(nèi)容處理為:
<img src="pic.gif" οnerrοr="javascript:this.src='/noPic.gif';" alt="pic">
這樣甥桂,注入的標(biāo)簽就失去了他的閉合性了,對(duì)一些普通的攻擊就進(jìn)行了防御邮旷,但是onerror事件是專門針對(duì)js出錯(cuò)的黄选,所以,標(biāo)簽閉合性被破壞剛好觸發(fā)了這個(gè)事件婶肩,所以办陷,他會(huì)被執(zhí)行,執(zhí)行之后將img標(biāo)簽的src屬性替換成我們想要的屬性律歼,然而我注入的這個(gè)地址懂诗,故意又是一個(gè)不能訪問的地址,于是苗膝,就反復(fù)的觸發(fā)這個(gè)onerror事件殃恒,最終導(dǎo)致瀏覽器堆棧溢出了。
說明:如果圖片存在辱揭,但網(wǎng)絡(luò)很不通暢离唐,也可能觸發(fā) onerror。
解決方法:
-
1问窃、用html轉(zhuǎn)義亥鬓,將<>轉(zhuǎn)義成轉(zhuǎn)義符,這樣標(biāo)簽就編程了文本了(QQ空間的做法) - 2域庇、使用jsoup白名單過濾掉onerror關(guān)鍵字嵌戈,讓他不要在前臺(tái)顯示(這種更安全,因?yàn)檗D(zhuǎn)義還有可能被繞過)
10, split() join() 的區(qū)別
前者是將字符串切割成數(shù)組的形式听皿,后者是將數(shù)組轉(zhuǎn)換成字符串
11, 閉包
熟呛。。尉姨。庵朝。
12,display 有哪些值及其區(qū)別
13又厉,position 有哪些值及其區(qū)別
14九府, px、em覆致、rem 區(qū)別
15侄旬,CSRF攻擊和防御
防御:
1,盡量使用post請(qǐng)求
2煌妈,加入驗(yàn)證碼
3儡羔,驗(yàn)證Referer
4.Token
5, 加入自定義header
16, XSS原理和防御
XSS 攻擊婆排,即跨站腳本攻擊(Cross Site Scripting),它是 web 程序中常見的漏洞笔链。
原理
攻擊者往 web 頁(yè)面里插入惡意的 HTML 代碼(Javascript段只、css、html 標(biāo)簽等)鉴扫,當(dāng)用戶瀏覽該頁(yè)面時(shí)赞枕,嵌入其中的 HTML 代碼會(huì)被執(zhí)行,從而達(dá)到惡意攻擊用戶的目的坪创。如盜取用戶 cookie 執(zhí)行一系列操作炕婶,破壞頁(yè)面結(jié)構(gòu)、重定向到其他網(wǎng)站等莱预。
17,for in for of區(qū)別
1,for in 取的是key for of 取的是value
2, for in 可以用于數(shù)組和對(duì)象 for of只能用于數(shù)組遍歷
charAt() 返回指定位置的字符
去掉var str = "wangaaaallla"出現(xiàn)最多的字符柠掂,并統(tǒng)計(jì)出現(xiàn)次數(shù)
let str = "wangaaaallla"
function getStr (str) {
let obj = {}
for (var i = 0; i < str.length; i++) {
console.log(obj[str.charAt(i)])
if (obj[str.charAt(i)]) {
obj[str.charAt(i)]++
} else {
obj[str.charAt(i)]=1
}
}
let sum = 0
let number
for (let i in obj) {
if (obj[i]>sum) {
sum=obj[i]
number=i
}
}
console.log(number+'出現(xiàn)了====='+sum+'次');
}
getStr(str)
18, 獲得并解析url中的參數(shù) 比如url: http://NaoNao.com/?product=shirt&color=blue&newuser&size=m#Hello
function UrlSearch() {
var name,value;
var args = {}
var str='http://NaoNao.com/?product=shirt&color=blue&newuser&size=m#Hello'; //取得整個(gè)地址欄
var num=str.indexOf("?") // 18
str=str.substr(num+1); //取得所有參數(shù) product=shirt&color=blue&newuser&size=m#Hello
var arr=str.split("&"); //各個(gè)參數(shù)放到數(shù)組里
for(var i=0;i < arr.length;i++){
num=arr[i].indexOf("="); // 7 5 -1 4
if(num>0){
name=arr[i].substring(0,num);
value=arr[i].substr(num+1);
args[name] = value
}
}
console.log(args) // {product: "shirt", color: "blue", size: "m#Hello"}
return args
}
UrlSearch()
substring() 方法用于提取字符串中介于兩個(gè)指定下標(biāo)之間的字符
var str="Hello world!"
undefined
str.substring(3, str.length)
"lo world!"
substr() 方法可在字符串中抽取從 start 下標(biāo)開始的指定數(shù)目的字符
var str="Hello world!"
undefined
str.substring(3, str.length)
"lo world!"
slice() 方法可提取字符串的某個(gè)部分,并以新的字符串返回被提取的部分依沮。
var str="Hello happy world!"
undefined
str.slice(6)
"happy world!"
19,JS實(shí)現(xiàn)排序
1涯贞,冒泡排序 bubble
思想: 讓數(shù)組中的當(dāng)前項(xiàng)和后一項(xiàng)比較,如果當(dāng)前項(xiàng)大于后一項(xiàng)危喉,則兩者交換位置
let ary = [12, 8, 24, 16, 1]
function bubble (v) {
for (let i = 0; i < v.length-1; i++) { // 外層循環(huán)i控制比較的輪數(shù)
for (let j = 0; j < v.length-i-1; j++) { // 里層循環(huán)控制每一輪比較的次數(shù)
if (v[j] > v[j + 1]) {
[v[j], v[j + 1]] = [v[j + 1], v[j]]
}
}
}
console.log(v) // [1, 8, 12, 16, 24]
return v
}
bubble(ary)
2宋渔,插入排序 insert
let ary = [12, 8, 24, 16, 1]
function insert (v) {
let arr = []
arr.push(v[0])
for (var i = 1; i < v.length; i++) {
let temp = v[i]
for (var j = arr.length - 1; j >= 0; j--) {
let _a = arr[j]
if (temp > _a) {
arr.splice(j + 1, 0, temp)
break
}
if (j === 0) {
arr.unshift(temp)
}
}
}
console.log(arr) // [1, 8, 12, 16, 24]
return arr
}
insert(ary)