Summary of front-end technology
precompiled
function fn(a,c){
console.log(a) //f a(){}
var a = 123
console.log(a) / / 123
console.log(c) //f c(){}
function a(){}
if(false) {var d=678
}
console.log(d)//undefined
console.log(b)//undefined
var b =function() {}
console.log(b)//f(){}
function c(){}
console.log(c)//f c(){}
}
fn(1.2)
/ / the precompiled
// Scope creation phase precompile phase
// What was done during precompilation
The AO object is accessed by the JS engine itself
// the function declaration overwrites the variable declaration. // The function declaration overwrites the variable declarationAO: {a:undefined 1 function a(){}
c:undefined 2 function c(){}
d:undefined
b:undefined
}
Copy the code
This points to the problem
Used directly in functions
function get(content){
console.log(content)
}
get('hello')// can be thought of as syntactic sugar for the following statements
get.call(window.'hello')
Copy the code
A function is called as a method of an object (to whom it is called).
var person = {
name:'Joe'.run:function(time){
console.log(`The ${this.name}In running the most${time}Min is not ')
}
}
person.run(30)// can be thought of as syntactic sugar for the following statements
person.run.call(person,30)
Copy the code
List the topic
var name=222
var a ={
name:111.say:function(){
console.log(this.name)
}
}
var fun = a.say
fun() //fun,call(window) 222
a.say()//a.say.call(a) 111
var b={
name:333.say:function(fun){
fun()
}
}
b.say(a.say)// When passed in, this is equivalent to fun()= a.sage, which is equivalent to the first type 222
b.say = a.say
b.say()//b calls equal to console.log(this.name) copied to B's say method 333
Copy the code
This in the arrow function
-
The this in the arrow function is bound when the function is defined, not when the function is executed
-
In the arrow function, the this point is fixed, not because the arrow function has a mechanism to bind this. The actual reason is that the arrow function does not have its own this, so the internal this is the this of the outer code block. Because it does not have this, it cannot be used as a constructor
var x =11 var obj={ x:22.say:() = >{ console.log(this.x) } } obj.say() // The output is 11 Copy the code
var obj={ birth:1990.getAge:function(){ var b=this.birth var fn=() = >new Date().getFullYear()-this.birth return fn() } } console.log(obj.getAge())// Output is 2021-1990=31 Copy the code
Since the arrow function is defined in getAge() and its parent is the obj inner scope, the this in its arrow function points to the parent OBj object, this.birth is 1990
Depth and light copy in js
Assignment: when we put an object is assigned to a new variable, assign a is actually the addresses of objects in the stack, rather than a pile of data, namely two object point to the same storage space, no matter which object changed, actually is to change the content of the storage space, so the two objects are linked
Shallow copy: The basic data types of objects before and after the copy do not affect each other. However, the reference types of objects before and after the copy do affect each other because they share the same memory block
Deep copy: Creates a new area of the heap to hold objects, the original object and the new object are not affected by each other
operation | And whether the original data points to the same object | The first layer of data is of general data type | Layer 1 data is not a generic data type |
---|---|---|---|
The assignment | is | Change changes the raw data | Change alters the raw data |
Shallow copy | no | Change doesn’t change the raw data | Change alters the raw data |
Deep copy | no | Change doesn’t change the raw data | Change doesn’t change the raw data |
-
Assignment code
var person = { name:"Zhang".hobby: ['learning'.'Knock code'.'eat the melon']}var person1 = person person1.name = "Bill" person1.hobby[0] ='play' console.log(person)// Both name:" Lisi "hobby:[' play ',' code ',' eat '] console.log(person1) Copy the code
-
Shallow copy code (base data types are not affected, reference data types are changed at the same time)
var person = { name:"Zhang".hobby: ['learning'.'Knock code'.'eat the melon']}function shallowCopy(obj){ var target = {} for(var i in obj){ if(obj.hasOwnProperty(i)){ target[i]=obj[i] } } return target } var person1 = shallowCopy(person) person1.name='the king 2' person1.hobby[0] ="Play" console.log(person)// Joe plays code and eats melon console.log(person1)// Wang er play code eat melon Copy the code
-
Deep-copy code (data is not affected before and after copying)
var person = { name:"Zhang".hobby: ['learning'.'Knock code'.'eat the melon']}function deepClone(obj){ var cloneObj = new obj.constructor() if(obj===null) return obj if(obj instanceof Date) return new Datr(obj) if(obj instanceof RegExp) return new RegExp(obj) if(typeofobj ! = ='object') return obj for(var i in obj){ if(obj.hasOwnProperty(i)){ cloneObj[i]=deepClone(obj[i]) } } return cloneObj } Parse (json.stringify (person))// Var person1 = json.parse (json.stringify (person) var person1 = deepClone(person) person1.name="Hututu" person1.hobby[0] ="Playing mahjong" console.log(person1)// Both have no effect at all console.log(person) Copy the code
Shallow copy implementation
- CloneObj in Lodash
- . Expansion operator
- Array.prototype.concat()
- Array.prototype.slice()
Deep copy implementation
- Json.parse (json.stringify ()) will raise an exception if there are regular expressions, Date objects, regular objects, and Promises in the object
- Recursive implementation (as in the code above)
- cloneDeep()
- jquery.extend()
Image stabilization
You can use closures
var input = document.querySelector('input')
function debounce(delay){
let timer
return function(value){
clearTimeout(timer)
timer=setTimeout(function(){
console.log(value)
},delay)
}
}
var debounceFunc = debounce(1000)
input.addEventListener('keyup'.function(e){
debounceFunc(e.target.value)
})
Copy the code
Using closures, the return function can also use a timer, which is generated only once when debounce is called
The throttle
Do one thing at a time, no matter how many clicks, and wait until the second thing is done. Closures solve throttling
document.querySelector('button').addEventListener('click',thro(handle,2000))
function thro(func,wait){
let timeout
return function(){
if(! timeout){ timeout =setTimeout(function(){
func()
timeout=null
},wait)
}
}
}
function handle(){
console.log(Math.random())
}
Copy the code
The underlying principles of closures
function a(){
var aa=123
function b(){
var bb = 234
console.log(aa)
}
return b
}
var res = a()
res()// can output 123
Copy the code
After a() is executed, the corresponding scope chain of A will be broken, but B can access the scope chain of A when defining. This scope chain will not be broken, so res() can still access aa=123, which can output 123. The closure can keep the variable in memory all the time.
Closures implement the singleton pattern
var createLogin = function () {
var div = document.createElement('div')
div.innerHTML = "I'm the div that pops up."
div.style.display = 'none'
document.body.appendChild(div)
return div
}
var getSingle = function(fn){
var result
return function(){
return result || (result=fn.apply(this.arguments))}}var create = getSingle(createLogin)
document.querySelector('button').onclick=function(){
var loginLay = create()
loginLay.style.display = "block"
}
Copy the code
Create only one div, no matter how many times you click
Js runtime mechanism
Js is a single thread, because JS is inseparable from the operation of the user. Assuming that JS is multi-threaded, it is impossible to create and delete the same DOM at the same time when operating dom
arguments
function get(){
console.log(arguments)
}
get(1.2.3)
// Arguments is an array object of class
/ / by Array. Prototype. Slice. The call (the arguments) is transformed into an Array
// It can also be converted to an array using the expansion operator in ES6
Copy the code
Why does b in the code become a global variable when this function is called
function func(){
let a=b=3
}
func()
console.log(b)/ / 3
console.log(a)//error
Copy the code
Because let a=b=3 is equivalent to let a=(b=3), b is not declared, so it will become a global variable when it is created. After func() is executed, b is a global variable, so it can be accessed, but a is in func() scope and cannot be accessed externally
Which operations cause memory leaks
- closure
- Unexpected global variables
- The forgotten timer
- An out-of-dom reference (for example, var div=document.querySelector(‘div’) is then removed, but the reference to div is not removed, and the reference to div remains in memory)
Higher-order functions
A function that takes a function as an argument or return value
function highOrder(params,callback){
return callback(params)
}
Copy the code
Write a map
var arr=[1.2.3]
function map(arr,mapCallback){
// Check if the parameters are correct
if(!Array.isArray(arr)||! arr.length||typeofmapCallback! = ="function") {return []}
else{
let result = []
for(let i=0; i<arr.length; i++){ result.push(mapCallback(arr[i],i,arr))//1 for each item 2, index 3 is passed into the array
}
return result
}
}
var res = map(arr,(item) = >{
return item*2
})
console.log(res)/ / 2 minus 2
Copy the code
Js event loop mechanism
-
Asynchronous operations in JS, such as fetch setTimeout setInterval, will be pushed into the call stack and the message will be put into the message queue. The message queue will be executed after the call stack is empty
-
The asynchronous operation of the Promise async await will be added to the microtask and will be executed as soon as the call stack empties and the microtask added to the call stack is executed as soon as possible
Js singleton mode
- Definition 1. only one instance 2. globally accessible
- Main problem solved: a globally used class is frequently created and destroyed
- When to use: When you want to control the number of instances and save systematic resources
- How to implement: determine whether the system has this singleton, if so return, not create
- Advantages of the singleton pattern: Having only one instance in memory reduces memory overhead especially for frequent instance creation and destruction (such as the cache of the home page)
Es6 Creates a singleton
class Person{
constructor(name,sex,hobby){
this.name = name
this.sex = sex
this.hobby = hobby
}
static getInstance(name,sex,hobby){
if(!this.instance){
this.instance = new Person(name,sex,hobby)
}
return this.instance
}
}
let person1 = Person.getInstance('hututu'.'male'.'eat the melon')
let person2 = Person.getInstance('Handsome Hu'.'woman'.'Beat the beans')
console.log(person1==person2)//true
console.log(person1)//' hututu ',' male ',' melon '
console.log(person2)
Copy the code
The strategy pattern
- Definition of a policy pattern: Define a series of algorithms, encapsulate them one by one, and make them interchangeable
- The strategy pattern refers to defining a set of algorithms and encapsulating them one by one. Separating the immutable from the changing is the theme of every design pattern, and policy patterns are no exception. The purpose of policy patterns is to separate the use of algorithms from the implementation of algorithms
var registerForm = document.querySelector('.registerForm')
var strategies = {
isNonEmpty: function(value,errorMsg){
if(value == ' ') {return errorMsg}
},
minLength:function(value,length,errorMsg){
if(value.length<6) {return errorMsg}
},
isMobile:function(value,errorMsg){
if(!/ ^ 1 [3 5 | | 5] [0-9] {9} $/.test(value)){return errorMsg}
}
}
// New Validator()
var validataFun = function(){
var validator = new Validator()
// Add validation rules
validator.add(registerForm.username,'isNonEmpty'.'User name cannot be empty')
validator.add(registerForm.password,'minLength:6'.'Password length must not be less than 6 characters')
validator.add(registerForm.username,'isMobile'.'Mobile phone number format is not correct')
// Enable authentication
var errorMsg = validator.start()
return errorMsg
}
registerForm.onsubmit = function(){
var errorMsg = validataFun()
if(errorMsg){
alert(errorMsg)
return false}}// Encapsulate the policy class constructor class
var Validator = function(){
// Saves an array of validation rules
this.cache=[]
}
Validator.prototype.add = function(dom,rule,errorMsg){
var arr = rule.split(':')
this.cache.push(function(){
var strategy = arr.shift()
arr.unshift(dom.value)
arr.push(errorMsg)
returnstrategies[strategy](... arr) }) } Validator.prototype.start =function(){
for(var i=0,vaFunc; vaFunc =this.cache[i++];) {var msg = vaFunc()
if(msg){
return msg
}
}
}
Copy the code
BFC
-
Definition: block-level formatting context, which refers to a separate block-level rendering area with only block-level BOX participation. This area has a set of rendering rules that constrain the layout of the block-level BOX, independent of the area outside
Let’s start with a phenomenon
A box father does not set height, and cannot lift itself when the son element is floating, i.e., the height of father is always 0, and the box does not form a BFC
-
How do I create a BFC
- The value of float is not None
- The value of position is not static or relative
- The value of display is inline-block, flex, or inline-flex
- Overflow: Hidden (a better way not to affect the external layout)
-
Other functions of the BFC
- Margin collapse can be eliminated
- Prevents elements from being overwritten by floating elements
Array flattening
-
Arrays come with flattening methods
const arr = [1[2[3[4.5]]].6] console.log(arr.flat(Infinity)) Copy the code
-
Regular add JSON. Parse (JSON. Stringify (arr))
-
recursive