Nowadays, the technical requirements of front-end engineers are becoming higher and higher, and the ability to use common apis can no longer meet the pace of the rapid development of front-end. Nowadays, most big and medium factories will require candidates to write the principle of common front-end API to prove your understanding of the knowledge point. Next, I will list my interview and think more important CSS part, JS part of the common handwriting principle questions!
The CSS part
Classic Flex layout
Flex layouts are now widely used on both mobile and PC, so here are a few requirements that are common in everyday projects. In the following examples, we will use the Vue project as an example
Flex layout evenly distributed after line break problem
Requirement 1: There are multiple Li’s under UL, every three Li’s are in a row, and the extra line breaks are displayed.
Obviously, most of your friends use Flex layouts, and obviously there is a problem that if Li is a multiple of 3 it will work, if not, the layout will not be satisfactory to the product manager.
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
Copy the code
Solution:
We add li at the bottom of ul as the remainder of the total array length %3.
<li class="item" style="border: none;" v-for="(ite, idx) in list.length%3" :key="idx"></li>
Copy the code
A two-column layout
Two column layout: two columns left and right, fixed left, adaptive right
rendering
-
The first is floating
HTML part:
<div class="outer outer1"> <div class="left">1-left</div> <div class="right">1-right</div> </div> Copy the code
The CSS part:
.outer1 .left { width: 200px; float: left; } .outer1 .right { width: auto; margin-left: 200px; } Copy the code
-
The second way is flex
HTML part:
<div class="outer outer2"> <div class="left">2-left</div> <div class="right">2-right</div> </div> Copy the code
The CSS part:
.outer2 { display: flex; } .outer2 .left { flex: 0 0 200px; /* flex-grow: 0; flex-shrink:0; flex-basis:200px; */ } .outer2 .right { flex: auto; } note: flex: 00 200px is short for flex: flex-grow flex-shrink flex-basisCopy the code
-
The third way – position
HTML part:
<div class="outer outer3"> <div class="left">3-left</div> <div class="right">3-right</div> </div> Copy the code
The CSS part:
.outer3 { position: relative; } .outer3 .left { position: absolute; width: 200px; } .outer3 .right { margin-left: 200px; } Copy the code
-
The fourth way — position again
HTML part:
<div class="outer outer4"> <div class="left">4-left</div> <div class="right">4-right</div> </div> Copy the code
The CSS part:
.outer4 { position: relative; } .outer4 .left { width: 200px; } .outer4 .right { position: absolute; top: 0; left: 200px; right: 0; } Copy the code
Three column layout
Three column layout: the middle column has adaptive width, and the sides have fixed width
rendering
-
The first way — positioning
HTML part:
<div class="outer outer1"> <div class="left">1-left</div> <div class="middle">1-middle</div> <div class="right">1-right</div> </div> Copy the code
The CSS part:
.outer1 { position: relative; } .outer1 .left { position: absolute; width: 100px; } .outer1 .middle { margin: 0 200px 0 100px; } .outer1 .right { position: absolute; width: 200px; top: 0; right: 0; } Note: Use absolute positioning for left and right, and set margins in the middleCopy the code
-
The second way – Flex layout
HTML part:
<div class="outer outer2"> <div class="left">2-left</div> <div class="middle">2-middle</div> <div class="right">2-right</div> </div> Copy the code
The CSS part:
.outer2 { display: flex; } .outer2 .left { flex: 0 0 100px; } .outer2 .middle { flex: auto; } .outer2 .right { flex: 0 0 200px; } Copy the code
-
The third way – floating principle
HTML part:
<div class="outer outer3"> <div class="left">3-left</div> <div class="right">3-right</div> <div class="middle">3-middle</div> </div> Copy the code
The CSS part:
.outer3 .left{ float: left; width: 100px; } .outer3 .right { float: right; width: 200px; } .outer3 .middle { margin: 0 200px 0 100px; } Copy the code
The holy grail layout
Holy cup layout: middle priority rendering, separate left, middle and right structures
Steps to achieve the Grail layout:
- Let the left and right float in a row display, relative positioning
- Make the middle width of the middle module 100%
- Move the left color block to the front of middle, margin-left:-100%
- Move the right color block behind the middle, margin-left:- width
- Add an padding property padding to the parent elements of the three small blocks to squeeze the padding into the middle
- Move the left block to the left:-200px, move the right block to the right:-200px
rendering
HTML part:
<header>header</header>
<div class="container">
<div class="middle">midlle</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
<footer>footer</footer>
Copy the code
The CSS part:
header, footer {
height: 100px;
width: 100%;
background-color: antiquewhite;
}
.container {
height: 200px;
padding-left: 200px;
padding-right: 300px;
}
.container > div {
float: left;
position: relative;
height: 100%;
}
.left {
width: 200px;
height: 200px;
background-color: burlywood;
margin-left: -100%;
left: -200px;
}
.right {
width: 300px;
height: 200px;
background-color: burlywood;
margin-left: -300px;
right: -300px;
}
.middle {
width: 100%;
height: 200px;
background-color: #b0f9c2;
}
Copy the code
Twin wing layout
Twin wing layout
Specific steps to achieve the layout of twin flying wings:
- Float left, center and right on one line
- Give middle a width of 100%
- Make the left module move the left margin-left of the middle :-100%
- Make the right module move the middle’s right margin-left:- its own width
- Add outer spacing margin to middle container: left and right
Effect:
HTML part
<div class="main">
<div class="middle">
<div class="middle-inner"> middle </div> </div> <div class="left"> left </div> <div class="right"</div> </div>Copy the code
The CSS part
.main>div {
float:left;
position: relative;
height: 300px;
}
.middle {
width: 100%;
background-color: lightgreen
}
.left {
width:200px;
margin-left:-100%;
background-color:#b0f9c2
}
.right {
width: 200px;
margin-left:-200px;
background-color:pink
}
.middle-inner{
margin:0 200px;
background-color: burlywood;
height:300px;
}
Copy the code
Horizontal and vertical center
HTML part
<div class="box" id="box"Word-wrap: break-word! Important; "> < div style =" max-width: 100%;Copy the code
The CSS part
Public sector
body {
width: 100vw;
height: 100vh;
overflow: hidden;
}
.box {
box-sizing: border-box;
width: 100px;
height: 50px;
line-height: 50px;
text-align: center;
font-size: 16px;
border: 1px solid lightblue;
background: lightcyan;
}
Copy the code
The first is positioning
.box {
position: absolute;
top: 50%;
left: 50%;
margin-left: -50px;
margin-top: -25px;
}
Copy the code
Note: The above method is to be sure to know the specific width and height. But the following way is to know the width and height without using the width and height.
Second: Flex
body {
display: flex;
justify-content: center;
align-items: center;
}
Copy the code
Note: This approach is also not very compatible
Third: JavaScript
lethtml = document.documentElement, winW = html.clientWidth, winH = html.clientHeight, boxW = box.offsetWidth, // boxH = box. box.style.position ='absolute';
box.style.left = (winW - boxW) / 2 + 'px';
box.style.top = (winH - boxH) / 2 + 'px';
Copy the code
Type 4: table-cell
body {
display: table-cell;
vertical-align: middle;
text-align: center;
}
Copy the code
JS part
Count the tags that appear on web pages
Implementation steps:
- Get all DOM nodes
- The NodeList collection is converted to an array
- Gets the label name of each element of the array
- duplicate removal
new Set([...document.querySelectorAll(The '*')].map(ele=>ele.tagName)).size
Copy the code
JS deep and shallow copy
Object depth copy, is one of the common interview questions.
Original object:
let obj = {
a: 100,
b: [100, 200, 300],
c: {
x: 10
},
d: /^\d+$/
}
Copy the code
Shallow clone
Shallow clones clone only the first layer
Method one:
letobj2 = {... obj};Copy the code
Method 2:
let obj2 = {};
for(let key in obj) {
if(! obj.hasOwnProperty(key))break;
obj2[key] = obj[key];
}
Copy the code
A deep clone
Note: Functions, dates, regular expressions, and json.stringify are all converted to objects {}
Method one:
let obj3 = JSON.parse(JSON.stringify(obj));
Copy the code
Method 2:
functionDeepClone (obj) {// Filter some special casesif(obj === null) return null;
if(typeof obj ! = ="object") return obj;
if(typeof window ! = ='undefined'&&window. JSON) {// Browsers that support window.JSON use JSONreturn JSON.parse(JSON.stringify(obj));
}
if(obj instanceof RegExp) {// regularreturn new RegExp(obj);
}
if(obj instanceof Date) {// Datereturnnew Date(obj); } / /let newObj = {}
// let newObj = new Object()
letnewObj = new obj.constructor; // The purpose of not creating an empty object directly: the result of cloning and the previous class = "can clone an ordinary object, but also can clone an instance objectfor(let key in obj) {
if(obj.hasOwnProperty(key)) { newObj[key] = deepClone(obj[key]); / /}}let newObj = obj.constructor === Array ? [] : {};
//for(let key in obj) {
// newObj[key] = typeof obj[key] === 'object'? deepCopy(obj[key]) : //obj[key]; / /}return newObj;
}
Copy the code
Native Ajax
A complete Ajax request generally consists of the following steps:
- Instantiate the XMLHttpRequest object
- Connecting to the server
- Send the request
- introduce
function ajax(options) {
let method = options.method || 'GET'Params = options.params, // data = options.data, Url = options.url + (params?'? ' + Object.keys(params).map(key => key + '=' + params[key]).join('&') : ' '),
async = options.async === false ? false : true,
success = options.success,
headers = options.headers;
letxhr; // Create an XHR objectif(window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
success && success(xhr.responseText);
}
}
xhr.open(method, url, async);
if(headers) {
Object.keys(Headers).forEach(key => xhr.setRequestHeader(key, headers[key]))
}
method === 'GET' ? xhr.send() : xhr.send(data)
}
Copy the code
Note: IE5 and ie6 are not XMLHttpRequest compatible, so use the ActiveXObject() object and pass in ‘microsoft.xmlhttp’ for compatibility purposes.
-
ReadyState:
0 – (uninitialized) The send() method has not been called
1 – (load) The send() method has been called and the request is being sent
2 – (load completed) The send() method is complete and all responses have been received
3 – (Interaction) Parsing the response content
4 – (Done) The response content is parsed and can be invoked on the client side
Anti-shake and throttling
Nowadays, the front-end interface is more and more complex, and some frequent operations may cause low page performance and user experience. For example: input box search will frequently adjust the port interface, zoom in and out of the window, etc.
When an event is continuously triggered and no event is triggered for a certain period of time, the event handler is executed once. If the event is triggered again before the specified time, the delay starts again.
const debounce = (fn, delay) => {
let timer = null;
return(... args) => { clearTimeout(timer); timer =setTimeout(() => {
fn.apply(this, args);
}, delay);
};
};
Copy the code
Throttle-throttle Ensures that event handlers are invoked only once in a specified period of time when events are continuously emitted.
const throttle = (fn, delay = 500) => {
let flag = true;
return(... args) => {if(! flag)return;
flag = false;
setTimeout(() => {
fn.apply(this, args);
flag = true;
}, delay);
};
};
Copy the code
Parsing URL parameters
functionParseParam (url) {// Put the browser address in '? 'const paramsStr = /.+\? (.+)$/.exec(url)[1]; Const paramsArr = paramsstr.split (const paramsArr = paramsstr.split ('&'); // define the parsed objectletparamsObj = {}; // Run the paramsarr. forEach(param => {// Check whether there are keys and valuesif(/=/.test(param)) {// Structure gets the key and value of the objectlet [key, val] = param.split('='); // decodeURIComponent(val); Val = /^\d+$/.test(val)? parseFloat(val) : val; // Check whether there is a key attribute in the storage objectif(paramsObj. HasOwnProperty (key)) {// Store an array if it exists paramsObj[key] = []. Concat (paramsObj[key], val); }elseParamsObj [key] = val; // paramsObj[key] = val; }}else{// paramsObj[param] = in the case of no valuetrue; }})return paramsObj;
}
Copy the code
let url = 'https://www.baidu.com?username=%22tmc%22&password=%22123456%22&dutiy=%E5%89%8D%E7%AB%AF%E6%94%BB%E5%9F%8E%E7%8B%AE&flag ';
console.log(parseParam(url))
{ username: '"tmc"',
password: '" 123456",
dutiy: 'Front Siege Lion',
flag: true
}
Copy the code
The principle of the json
function jsonp({url, params, cb}) {
return new Promise((resolve, reject) => {
window[cb] = function(data) {/ / declare a global variable resolve (data). The document body. RemoveChild (script)} params = {... params, cb}let arrs = []
for(let key in params) {
arrs.push(`${key}=${params[key]}`)}let script = document.createElement('script')
script.src = `${url}?${arrs.join('&')}`
document.body.appendChild(script)
})
}
Copy the code
Disadvantages of JSONP:
- Only Get requests can be sent. Post, PUT, and DELETE are not supported
- Unsafe XSS attack
Apply the principle of
The implementation principle of Apply is similar to the implementation principle of Call, except that the parameter form is different. – the array
Function.prototype.apply = function(content = window) {
content.fn = this;
letresult; // Check if there is a second argumentif(arguments[1]) { result = content.fn(... arguments[1]); }else {
result = content.fn();
}
delete content.fn;
return result;
}
Copy the code
Note: When apply passes null as the first argument, this in the function body points to the window.
The principle of the bind
The bind method creates a new function. When the new function is called, the first argument to bind() will be this when it runs, and the subsequent sequence of arguments will be passed as its arguments before the arguments passed.
Function.prototype.bind = function(content) {
if(typeof this ! ='function') {
throw Error('not a function');
}
let _this = this;
let args = [...arguments].slice(1);
return function F() {// Determine if it is used as a constructorif(this instanceof F) {
return _this.apply(this, args.concat([...arguments]))
}
return _this.apply(content, args.concat([...arguments]))
}
}
Copy the code
The principle of the call
Call syntax: fun.call(thisArg, arg1, arg2, arg3,…..)
The core principles of Call:
- Sets the function as a property of the object
- Execute and delete this function
- Execute the function by specifying this to the function and passing in the given argument
- If no argument is passed, the default point is window
Function.prototype.call2 = function(content = window) {// Check whether underfine and null //if(typeof content === 'undefined' || typeof content === null){
// content = window
// }
content.fn = this;
let args = [...arguments].slice(1);
letresult = content.fn(... args); delete content.fn;return result;
}
Copy the code
Note: When call passes null as the first argument, this in the function body points to the window.
The principle of the new
How to implement a new operator:
- First the function takes unquantified arguments. The first argument is the constructor, and the following arguments are used by the constructor
- Then internally create an empty object obj
- Because the obj object needs to access properties on the constructor prototype chain, we link the two through setPrototypeOf. This code is equivalent to obj.proto = con.prototype
- Bind obj to the constructor and pass in the remaining arguments
- Check whether the constructor returns an object. If it is, use the value returned by the constructor, otherwise use obj, thus ignoring the original value returned by the constructor
/** * create a new operator * @param {*} Con constructor * @param {... Any} args forgets the argument */ passed in the constructorfunctioncreateNew(Con, ... args) {letObj = {} // Create an object, SetPrototypeOf (obj, con.prototype) // link the Object to the constructor prototype // obj.__proto__ = con.prototype // equivalent to the aboveletResult = con.apply (obj, args) // Point this in the constructor to the object and pass the argumentreturn result instanceof Object ? result : obj
}
Copy the code
Note:
The new operator does several things:
- The new operator returns an object, so we need to create an object internally
- This object, the this in the constructor, can access any property mounted on this
- This object has access to properties on the constructor prototype chain, so you need to link the object to the constructor
- The original value should be ignored, and the returned object should be processed normally
The new operator has the following characteristics:
- The instance created by new through the constructor Test can access properties in the constructor as well as properties in the constructor stereotype chain, so the instance and constructor are connected by the stereotype chain through the new operator
- If the constructor returns the original value, the return value is meaningless
- If the constructor returns an object, the return value will be used normally, rendering the new operator useless
The principle of instanceof
Instanceof is used to check whether an object has a constructor’s Prototype property in its prototype chain
function instanceOf(left,right) {
let proto = left.__proto__;
let prototype = right.prototype
while(true) {
if(proto === null) return false
if(proto === prototype) return trueproto = proto.__proto__; }}Copy the code
Promise A+ specification principle
During the advanced end of the interview. Request handwritten Promise A+ spec source code is A must. For more details, see the full version of implementing the Promise/A+ specification step by step
class Promise {
constructor(executor) {
this.status = 'pending'Value = undefined // The value returned after successful initialization this.reason = undefined // The cause returned after failed initialization // Resolve to handle asynchro Resolve this. OnRejectedCallbacks = [] // Reject all failed callbacks /** * @param {*} value / / Const resolve = (value) => {/ / forget -> forget -> check => {if(this.status === 'pending') {
this.status = 'fulfilled'// This will be a big pity. Value = value // Assign the successful value to the promise // In order to solve the asynchronous resolve and return multiple promise layers This. OnResolvedCallbacks. ForEach (fn = > {fn () / / when the state into a successful state in turn perform all resolve function})}} const reject = (reason) = > {if(this.status === 'pending') {
this.status = 'rejected'/ / fails to state transition to success failure states rejected this. A tiny = "reason / / will return to assigned to the cause of failure promise this. OnRejectedCallbacks. ForEach (fn = > {fn () / / Execute all reject})}} executor(resolve, reject) // execute the promise callback} /** * that defines the promisethenThis is a big pity. @param {*} onFulfilled fulfilled */ this is a big pitythenThis is a big pity, onRejected) {// This is a big pitythenConst promise2 = new Promise((resolve, reject) => {if(this.status === 'fulfilled'// If the state is fulfilled, the value will be passed to the successful callbacksetTimeout (() = > {const x = onFulfilled (value) this. / / the value of x for likely promise | | 123 | |'123'. // Note that no value is returned when promise2 is calledsetTimeout The simulation enters the second event loop; Let the chicken come first, let the egg come firstif(this.status === 'rejected') {
setTimeout(() => {const x = onRejected(this.reason) // Resolve (promise2, x, resolve, promise1) reject) }, 0) }if(this.status === 'pending') {/ / record - > solve asynchronous enclosing onResolvedCallbacks. Push (() = > {setTimeout(() => {
const x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
}, 0)
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
const x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
}, 0)
})
}
})
returnpromise2; }} const resolvePromise = (promise2, x, resolve, reject) => {// console.log(promise2, x, resolve, reject)if(promise2 === x) {// If the value returned isthenThrow TypeError() if the method returns the same value'Circular reference'} // check if x is a promise; Note: Null typeof is also an object to excludeif(typeof x === 'function' || (typeof x === 'object'&& x ! == null)) { try { constthen= x.teng // get the return value on xthenMethods; Note that methods will report errors to catch exceptions; The reason of 111if(typeof then= = ='function'Call (x, y => {// resolve(y) // resolve(y); It is possible to return multiple nested promises resolvePromise(promise2, Y, resolve, reject)}, r => {reject(r)})} catch(e) {reject(e)}}else {
resolve(x);
}
}
module.exports = Promise;
Copy the code
JS array
duplicate removal
Ordinary items
let arr2 = [1, 2, 3, 2, 33, 55, 66, 3, 55];
The first:
let newArr = [];
arr2.forEach(item => {
if(newArr.indexOf(item) == '1') {
newArr.push(item);
}
})
console.log(newArr);
// (6) [1, 2, 3, 33, 55, 66]
Copy the code
The second:
let newArr = [...new Set(arr2)];
console.log(newArr);
// (6) [1, 2, 3, 33, 55, 66]
Copy the code
Note: array.from (), filter(), for(), etc.
Object to study
let arr1 = [
{id: 1, name: 'Tang Xiaomeng'},
{id: 2, name: 'Shi Xiaoming'},
{id: 3, name: 'Front-end development'},
{id: 1, name: 'the web front end'}];Copy the code
Implementation method:
const unique = (arr, key) => {
return [...new Map(arr.map(item => [item[key], item])).values()]
}
console.log(unique(arr1, 'id'));
// [
{id: 1, name: "The web front end"},
{id: 2, name: "Shi Xiaoming"},
{id: 3, name: "Front-end development"}]Copy the code
merge
let arr3 = ['a'.'b']
let arr4 = ['c'.'d']
Copy the code
Method 1: ES5
letarr5 = arr3.concat(arr4); console.log(arr5); / / /'a'.'b'.'c'.'d']
Copy the code
Method 1: ES6
letarr6 = [...arr3, ...arr4]; console.log(arr6); / / /'a'.'b'.'c'.'d']
Copy the code
flattening
let arr7 = [1, 2, [3, 4], [5, 6, [7, 8, 9]]];
Copy the code
The first:
let arrNew = arr7.flat(Infinity);
console.log(arrNew);
// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy the code
The second:
let arrNew = arr7.join().split(', ').map(Number);
console.log(arrNew);
// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy the code
The third:
let arrNew = arr7.toString().split(', ').map(Number);
console.log(arrNew);
// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy the code
Fourth:
const flattern = (arr) => {
const result = []
arr.forEach((item) => {
if(Array.isArray(item)) { result.push(... flattern(item)) }else {
result.push(item)
}
})
return result
}
flattern(arr7);
// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy the code
Fifth:
function flatten(arr) {
return[].concat( ... arr.map(x => Array.isArray(x) ? flatten(x) : x) ) } flattern(arr7); // (1) [1, 2, 3, 4, 5, 6, 7, 8, 9]Copy the code
Array or not
let arr = []
Copy the code
First: instanceof
console.log(arr instanceof Array)
Copy the code
B) constructor
console.log(arr.constructor === Array)
Copy the code
Third: some method for determining whether an object has an array such as push
console.log(!! arr.push && !! arr.concat)Copy the code
The fourth type: toString
console.log(Object.prototype.toString.call(arr) === '[object Array]')
Copy the code
Fifth: array. isArray
console.log(Array.isArray(arr))
Copy the code
Note: the fifth way is the best ~
Bubble sort
let arr = [1, 44, 6, 77, 3, 7, 99, 12];
Copy the code
- The principle of bubble sort algorithm is as follows:
- Compare two adjacent elements, and if the first is larger than the last, swap places
- The last element should be the largest in the first round
- Repeat this step for all elements except the last one
function bubbleSort(arr) {
for(let i=0; i<arr.length; i++) {
for(let j=0; j<arr.length - i - 1; j++) {
if(arr[j+1] < arr[j]) {
lettemp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; }}}returnarr; } console.log(bubbleSort(arr)); // [1, 3, 6, 7, 12, 44, 77, 99]Copy the code
Note: The last element is not compared.
Quick sort
let arr = [1, 44, 6, 77, 3, 7, 99, 12];
Copy the code
- The principles of quicksort algorithm are as follows:
- Find the benchmark (usually based on the middle term)
- Iterate over groups of numbers, leaving those less than the baseline at left and those greater than the baseline at right
- recursive
function quickSort(arr) {
if(arr.length <= 1) return arr;
let mid = Math.floor(arr.length / 2);
let midItem = arr.splice(mid, 1)[0];
let leftArr = [];
let rightArr = [];
for(let i=0; i<arr.length; i++) {
let current = arr[i];
if(current >= midItem) {
rightArr.push(current);
} else{ leftArr.push(current); }}returnquickSort(leftArr).concat([midItem], quickSort(rightArr)); } console.log(quickSort(arr)); // [1, 3, 6, 7, 12, 44, 77, 99]Copy the code
conclusion
Summary above I interview or interview others common CSS, JS part of the handwriting principle. Hope to have friends need to think carefully read, there will be harvest. Hope you get a satisfactory offer~❤️
The last
If this article has helped you, give it a thumbs up ❤️❤️❤️
Welcome to join us to learn the front end and make progress together!