做者: Yeaseon
Blog:yeaseonzhang.github.io
原文連接css
"金三銀四,金九銀十",用來形容求職最好的幾個月。可是隨着行業的飽和,初中級前端er就業形勢不容樂觀。html
行業狀態不可控,咱們能作的固然只是讓本身變得更加具備競爭力。前端
今年本身也用了幾個月的時間來準備筆記面試,鞏固基礎知識。特此將本身在這個過程總結的題目分享出來,但願對於求職和準備求職的同窗有所幫助。git
/* 1.添加新元素 */
<div class="outer">
<div class="div1"></div>
<div class="div2"></div>
<div class="div3"></div>
<div class="clearfix"></div>
</div>
.clearfix {
clear: both;
}
/* 2.爲父元素增長樣式 */
.clearfix {
overflow: auto;
zoom: 1; // 處理兼容性
}
/* 3.:after 僞元素方法 (做用於父元素) */
.outer {
zoom: 1;
&:after {
display: block;
height: 0;
clear: both;
content: '.';
visibillity: hidden;
}
}複製代碼
使用sass
語法。github
/* 定義 */
@mixin border-1px ($color) {
position: relative;
&:after {
display: block;
position: absolute;
left: 0;
bottom: 0;
width: 100%;
border-top: 1px solid $color;
context: '';
}
}
@media (-webkit-min-device-pixel-radio: 1.5), (min-device-pixel-radio: 1.5) {
border-1px {
&:after {
-webkit-transform: scaleY(0.7);
transform: scaleY(0.7);
}
}
}
@media (-webkit-min-device-pixel-radio: 2), (min-device-pixel-radio: 2) {
border-1px {
&:after {
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}
}
/* 使用方式 */
@inclue border-1px(rgba(7, 17, 27, .1));複製代碼
BFC全稱」Block Formatting Context」, 中文爲「塊級格式化上下文」。BFC元素特性表現原則就是,內部子元素再怎麼翻江倒海,翻雲覆雨都不會影響外部的元素。web
float
爲 left|right
overflow
爲 hidden|auto|scroll
display
爲 table-cell|table-caption|inline-block
position
爲 absolute|fixed
左定寬右自適應寬度,而且等高佈局(最小高度200px)shell
/* HTML */
<div class="container">
<div class="left">Left silder</div>
<div class="content">Main content</div>
</div>
/* CSS */
.container {
overflow: hidden;
}
.left {
float: left;
width: 200px;
margin-bottom: -9999px;
padding-bottom: 9999px;
background-color: #eee;
}
.content {
margin-left: 200px;
margin-bottom: -9999px;
padding-bottom: 9999px;
background-color: #ccc;
}
.left, .content {
min-height: 200px;
height: auto !important;
}複製代碼
async
與defer
區別異步(async) 腳本將在其加載完成後當即執行,而 延遲(defer) 腳本將等待 HTML 解析完成後,並按加載順序執行。跨域
location.replace()
與location.assign()
區別location.replace()
的url不會出如今history中數組
new
操做符this
變量引用該對象,同時還繼承了 該函數的原型this
引用的對象中this
所引用,而且最後隱式的返回this
/* AMD是RequireJS對模塊化的定義
* CMD是seaJS對模塊化的定義
* CommonJS是Node對模塊化的規範
**/
/* AMD 依賴關係前置 */
define(['./a', './b'], function (a, b) {
a.something();
b.something();
})
/* CMD 按需加載,依賴就近 */
define(function (require, exports, module) {
var a = require('./a');
a.something();
var b = require('./b');
b.something();
})複製代碼
// 建立節點
createDocumentFragment()
createElement()
createTextNode()
// 添加 移除 替換 插入
appendChild()
removeChild()
replaceChild()
insertBefore()
// 查找
getElementsByTagName()
getElementsByName()
getElementsByClassName()
getElementById()
querySelector()
querySelectorAll()複製代碼
/* 1.直接設置style屬性 */
element.style.height = '100px';
/* 2.直接設置屬性 */
element.setAttribute('height', '100px');
/* 3.使用setAttribute設置style屬性 */
element.setAttribute('style', 'height: 100px !important');
/* 4.使用setProperty設置屬性,經過第三個參數設置important */
element.style.setProperty('height', '300px', 'important');
/* 5.設置cssText */
element.style.cssText += 'height: 100px !important';複製代碼
function stopDefault( e ) {
// 阻止默認瀏覽器動做(W3C)
if ( e && e.preventDefault ) {
e.preventDefault();
} else {
// IE中阻止函數器默認動做的方式
window.event.returnValue = false;
}
return false;
}複製代碼
function stopBubble(e) {
// 若是提供了事件對象,則這是一個非IE瀏覽器
if ( e && e.stopPropagation ) {
// 所以它支持W3C的stopPropagation()方法
e.stopPropagation();
} else {
// 不然,咱們須要使用IE的方式來取消事件冒泡
window.event.cancelBubble = true;
}
}複製代碼
function Foo() {
getName = function () { alert(1); }
return this;
}
Foo.getName = function () { alert(2); }
Foo.prototype.getName = function () { alert(3); }
var getName = function () { alert(4); }
function getName () { alert(5); }
/* 寫出輸出 */
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();複製代碼
具體講解參見一道常被人輕視的前端JS面試題
slice
實現var arr = ['old', 1, true, null, undefined];
var new_arr = arr.slice();
new_arr[0] = 'new';
console.log(arr) // ["old", 1, true, null, undefined]
console.log(new_arr) // ["new", 1, true, null, undefined]複製代碼
concat
實現var arr = ['old', 1, true, null, undefined];
var new_arr = arr.concat();
new_arr[0] = 'new';
console.log(arr) // ["old", 1, true, null, undefined]
console.log(new_arr) // ["new", 1, true, null, undefined]複製代碼
以上兩種方法只是淺拷貝,若是數組元素是基本類型,就會拷貝一份新的;可是若是數組元素是對象或者數組,就只會拷貝引用(相似指針),修改其中一個就會影響另一個。
var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}];
var new_arr = arr.concat();
new_arr[0] = 'new';
new_arr[3][0] = 'new1';
console.log(arr) // ["old", 1, true, ['new1', 'old2'], {old: 1}]
console.log(new_arr) // ["new", 1, true, ['new1', 'old2'], {old: 1}]複製代碼
JSON.stringify
實現數組深拷貝var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}];
var new_arr = JSON.parse(JSON.stringify(arr));
new_arr[0] = 'new';
new_arr[3][0] = 'new1';
console.log(arr) // ["old", 1, true, ['old1', 'old2'], {old: 1}]
console.log(new_arr) // ["new", 1, true, ['new1', 'old2'], {old: 1}]複製代碼
簡單粗暴,可是問題是不能拷貝函數,不推薦。
而後咱們來手動實現深淺拷貝。
var shallowCopy = function (obj) {
// 判斷是不是數組或者對象
if (typeof obj !== 'object') {
return
}
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}複製代碼
var deepCopy = function (obj) {
if (typeof obj !== 'object') {
return
}
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
}
}
return newObj
}複製代碼
filter
+ indexOf
function unique (arr) {
var res = arr.filter(function (item, index, array) {
return array.indexOf(item) === index;
})
return res;
}複製代碼
filter
+ sort
function unique (arr) {
return arr.concat().sort().filter(function (item, index, array) {
return !index || item !== array[index - 1];
})
}複製代碼
ES6
function uniqu3 (arr) {
return [... new Set(arr)];
}複製代碼
reduce
var arr = [6, 4, 1, 8, 2, 11, 3];
function max (prev, next) {
return Math.max(prev, next)
}
console.log(arr.reduce(max));複製代碼
apply
var arr = [6, 4, 1, 8, 2, 11, 3];
console.log(Math.max.apply(null, arr));複製代碼
ES6
var arr = [6, 4, 1, 8, 2, 11, 3];
function max (arr) {
return Math.max(...arr);
}
console.log(max(arr));複製代碼
var arr = [];
for (var i = 0; i < 100; i++) {
arr[i] = i;
}
arr.sort(function () {
return 0.5 - Math.random();
});複製代碼
var arr = [1, [2, [3, 4]]];
function flatten(arr) {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
}
console.log(flatten(arr))複製代碼
// 冒泡
function bubbleSort2(arr) {
var len = arr.length;
for (var i = 0; i <= len - 1; i++) {
for (var j = 0; j <= len - i; j++) {
if (arr[j + 1] < arr[j]) {
var temp;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
// 快速排序
function quickSort(arr) {
if(arr.length == 0) {
return []; // 返回空數組
}
var cIndex = Math.floor(arr.length / 2);
var c = arr.splice(cIndex, 1);
var l = [];
var r = [];
for (var i = 0; i < arr.length; i++) {
if(arr[i] < c) {
l.push(arr[i]);
} else {
r.push(arr[i]);
}
}
return quickSort(l).concat(c, quickSort(r));
}複製代碼
1234567890 -> 1,234,567,890
function formatNum (num) {
return num.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
var num = '1234567890';
var res = formatNum(num);
console.log(res);複製代碼
var arr = [];
for (var i = 0; i < 100; i++) {
arr[i] = i;
}
arr.sort(function () {
return 0.5 - Math.random();
})複製代碼
即只保存內層函數的調用幀(只有開啓嚴格模式,纔會生效),只有再也不用到外層函數的內部變量,內層函數的調用幀纔會取代外層函數的調用幀,不然沒法進行「尾調用優化。
function factorial(n) {
if (n === 1) return 1;
return n * factorial(n-1);
}
factorial(5)
/* 優化尾遞歸 */
function factorial(n, total) {
if (n === 1) return total;
return factorial(n - 1, n * total);
}
factorial(5, 1)複製代碼
實現add(1,2)
和add(1)(2)
均輸出3
function add () {
let sum = 0;
Array.prototype.forEach.call(arguments, function (item, index){
if (typeof item !== 'number') {
return false;
} else {
sum += item;
}
})
var tmp = function () {
Array.prototype.forEach.call(arguments, function (item, index){
if (typeof item !== 'number') {
return false;
} else {
sum += item;
}
})
return tmp;
}
tmp.toString = function () {
return sum
}
return tmp;
}
add(1, 2); // 3
add(1)(2); // 3
add(1, 2, 3)(1, 4)(2, 2)(1) // 16複製代碼
str.padStart(targetLength [, padString])
str.padEnd(targetLength [, padString])複製代碼
values
和entries
函數Object.values(obj)
Object.entries(obj)複製代碼
getOwnPropertyDescriptors
函數Object.getOwnPropertyDescriptors(obj)複製代碼
function es8(var1, var2, var3,) {}複製代碼
async
關鍵詞定義的函數聲明瞭一個能夠異步執行的函數,返回一個AsyncFunction
類型的對象。fucntion fetchTextByPromise () {
return new Promise(resolve => {
setTimeout(() => {
resolve('es8');
}, 2000);
});
}
async function sayHello () {
const externalFetchedText = await fetchTextByPromise();
console.log(`Hello, ${externalFetchedText}`);
}
sayHello();複製代碼
var class2type = {};
'Boolean Number String Function Array Date RegExp Object Error Null Undefined'.split(' ').map((item, index) => {
class2type['[object ' + item + ']'] = item.toLowerCase();
})
function type (obj) {
return typeof obj === 'object' || typeof obj === 'function' ?
class2type[{}.toString.call(obj)] || 'object' : typeof obj;
}複製代碼
/*
* func:須要調用的函數
* wait: 防抖時間
* immediate:布爾值,是否當即執行
**/
var debounce = function (func, wait, immediate) {
var timeout;
return function () {
var context = this;
var args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) { // 是否當即執行func
var callNow = !timeout;
timeout = setTimeout(function () {
timeout = null;
}, wait);
if (callNow) {
func.apply(context, args);
}
} else {
timeout = setTimeout(function () {
func.apply(context, args);
}, wait);
}
}
}複製代碼
var TemplateEngine = function(tpl, data) {
var re = /<%([^%>]+)?%>/g, match;
while(match = re.exec(tpl)) {
tpl = tpl.replace(match[0], data[match[1]])
}
return tpl;
}
var template = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>'; console.log(TemplateEngine(template, { name: "Yeaseon", age: 24 })); // '<p>Hello, my name is Yeaseon. I\'m 24 years old.</p>';複製代碼
apply
、call
和bind
apply
和call
在嚴格模式下,未指定環境對象而調用函數,則this 值不會轉型爲window。除非明確把函數添加到某個對象或者調用apply()或call(),不然this 值將是undefined。
在非嚴格模式下,call、apply的第一個參數傳遞爲null或undefined時,函數體內的this會指向默認的宿主對象,在瀏覽器中則是window。
apply
、call
和bind
比較var obj = {
x: 81
};
var foo = {
getX: function () {
return this.x;
}
}
console.log(foo.getX.bind(obj)());
console.log(foo.getX.apply(obj));
console.log(foo.getX.call(obj));複製代碼
很明顯,bind
方法後面多了一對括號。也就是說,當你但願改變上下文環境以後而且當即執行,而是回調執行的時候(多用於事件監聽器函數),使用bind()
方法,而apply/call
則會當即執行函數。
function log(){
console.log.apply(console, arguments);
};
log(1); //1
log(1,2); //1 2複製代碼
log("hello world"); //(app)hello world複製代碼
function log(){
var args = Array.prototype.slice.call(arguments);
args.unshift('(app)');
console.log.apply(console, args);
};複製代碼
apply
實現bind
function bind (fn, context) {
return function () {
return fn.apply(context, argument);
}
}複製代碼
function createPerson(name, age, job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
};
return o;
}
var person1 = createPerson("Nicholas", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");複製代碼
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");複製代碼
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"複製代碼
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby", "Court"];
}
Person.prototype = {
constructor : Person,
sayName : function(){
alert(this.name);
}
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true複製代碼
extend()
方法function extend() {
// 默認不進行深拷貝
var deep = false;
var name, options, src, copy, clone, copyIsArray;
var length = arguments.length;
// 記錄要複製的對象的下標
var i = 1;
// 第一個參數不傳佈爾值的狀況下,target 默認是第一個參數
var target = arguments[0] || {};
// 若是第一個參數是布爾值,第二個參數是 target
if (typeof target == 'boolean') {
deep = target;
target = arguments[i] || {};
i++;
}
// 若是target不是對象,咱們是沒法進行復制的,因此設爲 {}
if (typeof target !== "object" && !isFunction(target)) {
target = {};
}
// 循環遍歷要複製的對象們
for (; i < length; i++) {
// 獲取當前對象
options = arguments[i];
// 要求不能爲空 避免 extend(a,,b) 這種狀況
if (options != null) {
for (name in options) {
// 目標屬性值
src = target[name];
// 要複製的對象的屬性值
copy = options[name];
// 解決循環引用
if (target === copy) {
continue;
}
// 要遞歸的對象必須是 plainObject 或者數組
if (deep && copy && (isPlainObject(copy) ||
(copyIsArray = Array.isArray(copy)))) {
// 要複製的對象屬性值類型須要與目標屬性值相同
if (copyIsArray) {
copyIsArray = false;
clone = src && Array.isArray(src) ? src : [];
} else {
clone = src && isPlainObject(src) ? src : {};
}
target[name] = extend(deep, clone, copy);
} else if (copy !== undefined) {
target[name] = copy;
}
}
}
}
return target;
};複製代碼
function EventTarget () {
this.handlers = {};
}
EventTarget.prototype = {
constructor: EventTarget,
addHandler: function (type, handler) {
if (typeof this.handlers[type] == 'undefined') {
this.handlers[type] = [];
}
this.handlers[type].push(handler)
},
fire: function (event) {
if (!event.target) {
event.target = this;
}
if (this.handlers[event.type] instanceof Array) {
var handlers = this.handlers[event.type];
for (var i = 0, len = handlers.length; i < len; i++) {
handlers[i](event);
}
}
},
removeHandler: function (type, handler) {
if (this.handlers[type] instanceof Array) {
var handlers = this.handlers[type];
for (var i = 0, len = handlers.length; i < len; i++) {
if (handlers[i] === handler) {
break;
}
}
handlers.splice(i, 1);
}
}
}複製代碼
document.domain複製代碼
window.postMessage
JSONP
跨域(只支持GET
)
function todo(data){
console.log('The author is: '+ data.name);
}
var script = document.createElement('script');
/* 向服務器www.yeaseonzhang.com發出請求。注意,該請求的查詢字符串有一個callback參數,用來指定回調函數的名字。 */
script.src = 'http://www.yeaseonzhang.com/author?callback=todo';
document.body.appendChild(script);
/* 服務器收到這個請求之後,會將數據放在回調函數的參數位置返回。 */
todo({"name": "fewjq"});
/* 因爲<script>元素請求的腳本,直接做爲代碼運行。這時,只要瀏覽器定義了todo函數,該函數就會當即調用。做爲參數的JSON數據被視爲JavaScript對象。*/複製代碼
websocket
跨域<link>
,選擇性加載