- First published on December 02, 2020
- Recommended reading duration: 1H
- Recommended reading target: beginner and intermediate front-end engineers, JavaScript enthusiasts
- The article does not cover
Promise
involvingLess array
Related, the arrays topic will be updated later, as wellAsynchronous programming
Features, of course, there are also a lot of common you like handwriting implementation did not appear, maybe one day you come back to see the update up
-
All the interview questions you want to know are here
-
The CSS header interview questions and reference answers have been modified on December 02, 2020
-
The interview questions and reference answers were published on November 30, 2020
Update record
- Added on 26 December 2020
Encapsulation of native Ajax
- Added on 08 December 2020
Form submission
preface
This is the third official article in the series. As a front-end developer, then HTML we threw out a piece, then CSS we also shared a simple, naturally turn to Js, and then directly to look at the “so-called” handwriting implementation. In fact, in the process of sorting out and learning, I found a truth: that is why these are platitudes, or topics. It’s not hard to see that these are the very basics of being a front-end developer, not to mention that various frameworks like this and scoped chain closure inheritance are ubiquitous in our actual development or in those frameworks. Say goodbye to anxiety and don’t sell it. Ps: Case code at the end of the article
Handwritten implementationajax
request
/* Encapsulate ajax functions * @param {string}opt.type HTTP connection mode, Url URL for sending requests * @param {Boolean} Opt. Async Specifies whether the request is asynchronous. True indicates that the request is asynchronous. False is the parameter sent by synchronous * @param {object}opt.data in the format of object type * @param {function}opt.success Ajax sends and receives successfully called callback function */
ajax (opt) {
opt = opt || {};
opt.method = opt.method.toUpperCase() || 'POST';
opt.url = opt.url || ' ';
opt.async = opt.async || true;
opt.data = opt.data || null;
opt.success = opt.success || function () {};let xmlHttp = null;
if (XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
} else {
xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
}
this.XHR = xmlHttp;
var params = [];
for (var key in opt.data) {
params.push(key + '=' + opt.data[key]);
}
var postData = params.join('&');
if (opt.method.toUpperCase() === 'POST') {
xmlHttp.open(opt.method, opt.url, opt.async);
xmlHttp.setRequestHeader('Content-Type'.'application/x-www-form-urlencoded; charset=utf-8');
xmlHttp.send(postData);
} else if (opt.method.toUpperCase() === 'GET') {
xmlHttp.open(opt.method, opt.url + '? ' + postData, opt.async);
xmlHttp.send(null);
}
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { opt.success(xmlHttp.responseText); }}; }Copy the code
Handwritten implementationform
The form submission
function submit(){
let xhr = new XMLHttpRequest()
xhr.onreadystatechange = function(){
if(xhr.readyState == 4) {if(xhr.status>=200&&xhr.status<300 || xhr.status ==304) {console.log(xhr.responseText)
}
}
}
xhr.open('post'.'https://jsonplaceholder.typicode.com/todos')
xhr.setRequestHeader('Content-Type'.'application/x-www-form-urlencoded')
let form = document.getElementById("user-info");
xhr.send(serialize(form));
}
Copy the code
Handwriting implementation of anti-shake function (debounce/ anti-shake)
- The first anti-shake function
let num =1
const container = document.querySelector('.container')
// Basic function content
function commonFnCon(){
container.innerHTML = num++
}
function baseShowNumber(){
commonFnCon()
console.log(this) // <div>num</div>
}
function firstShowNumber(){
commonFnCon()
console.log(this) // This refers to window
}
function firstDebounce(fn,wait){
let timerId = null;
return function (){
if(timerId) clearTimeout(timerId)
// In a word: if an event is triggered, it will not be triggered again for 1s
timerId = setTimeout(fn,wait)
}
}
// container.onmousemove = baseShowNumber
container.onmousemove = firstDebounce(firstShowNumber,1000)
Copy the code
- The second stabilization function resolves the orientation of this
let num =1
const container = document.querySelector('.container')
// Basic function content
function commonFnCon(){
container.innerHTML = num++
}
function baseShowNumber(){
commonFnCon()
console.log(this) // <div>num</div>
}
function secShowNumber(){
commonFnCon()
console.log('sec'.this) // This refers to window
}
function secDebounce(fn,wait){
let timerId = null;
return function (){
let ctx = this
console.log('ctx',ctx) BaseShowNumber
num
if(timerId) clearTimeout(timerId)
// In a word: if an event is triggered, it will not be triggered again for 1s
timerId = setTimeout(() = >{
// Bind the this of the current environment to the event function (baseShowNumber)
// Execute the event function
fn.apply(ctx)
},wait)
}
}
// container.onmousemove = baseShowNumber
container.onmousemove = secDebounce(secShowNumber,1000)
Copy the code
- The third anti – shake function fixes the event object being undefined
let num =1
const container = document.querySelector('.container')
// Basic function content
function commonFnCon(){
container.innerHTML = num++
}
function baseShowNumber(e){
commonFnCon()
console.log(e) // MouseEvent
console.log(this) // <div>num</div>
}
function thirdShowNumber(e){
commonFnCon()
}
function thirdDebounce(fn,wait){
let timerId = null;
return function (){
let ctx = this
let args = arguments
console.log('ctx',ctx) BaseShowNumber
num
console.log('args'.arguments) // Arguments happens to be a pseudo-array containing event objects
if(timerId) clearTimeout(timerId)
// In a word: if an event is triggered, it will not be triggered again for 1s
timerId = setTimeout(() = >{
// Bind the this of the current environment to the event function (baseShowNumber)
// Execute the event function
fn.apply(ctx,args)
},wait)
}
}
// container.onmousemove = baseShowNumber
container.onmousemove = thirdDebounce(thirdShowNumber,1000)
Copy the code
- summary
The above implementation is still not complete, so let’s explore it by ourselves and paste the anti-shake function in our enterprise project
const debounce = (fn, delay, isImmediate) = > {
var timer = null;
return function() {
var that = this;
var args = [].slice.call(arguments);
varcallNow = ! timer && isImmediate;if(timer) clearTimeout(timer);
// Not immediately executed
timer = setTimeout(function() {
timer = null;
if(! isImmediate) fn.apply(that, args); }, delay);// Execute immediately
if(callNow) fn.apply(that, args); }};export {
debounce
}
Copy the code
- The business scenario
- Click the button to refresh to prevent frequent refresh
- There is also the validation of forms (validation scenario for asynchronous call interfaces)
Implementing throttle functions by hand
- Know the throttle
Throttling is every once in a while, only one event is performed, and shaking is one thing that is triggered and no longer triggers this event within 1s
function throttle(func, wait) {
let timerId = null
let now = 0
return function(){
let context = this;
let args = arguments;
if(! timerId){ timerId =setTimeout(() = >{
timerId = null
func.apply(context,args)
},wait)
}
}
}
Copy the code
Handwriting depth copy (depth clone)
background
Dark copy is the star topic of the interview
Just to be clear, we’re going to be talking about reference types, and we’re going to be copying more complex data types like array objects
If your brother changes the layout of your house, you and your brother will come home with the same keys. They will look the same. So you are family.
How do you cut off the data, by making a new copy of it a shallow copy of it a superficial copy of it a deep copy of it an infinite copy of it
Shallow copy
Shallow copy: create a new object with the original property values of the old object (primitive type, copied primitive type; Reference type (memory address) an exact copy of an object whose address changes and affects each other
let obj1 = {
name: "Zhang".age: 18};let obj2 = obj1;
obj2.name = "Bill";
console.log(obj1.name); // The name attribute of the first object is changed
Copy the code
And what we found is that we did this with a simple assignment and can we do it with a simple function, which is theta
const shallow = (target) = > {
let obj = {};
for (let prop intarget) { obj[prop] = target[prop]; }};Copy the code
If you look at the array
let targetArr = [{name:'oldName'},"1"."1".1.1.true.true.undefined.undefined.null.null,]
let resultArr = targetArr.concat()
resultArr[0] ['name'] = 'newName'
console.log('old',targetArr) // The name of the first element in the targetArr is also changed
console.log('new',resultArr)
Copy the code
The specific implementation
function firstShallowClone(target){
if(typeoftarget ! = ='object') return
let result = Array.isArray(target) ? [] : {}for(let k in target){
if(target.hasOwnProperty(k)){
result[k] = target[k]
}
}
return result
}
Copy the code
Deep copy
The core idea of deep copy is copy plus recursion which means that when a property of an object is still an object, we need to copy it further, copy it in full from memory, reopen the interval in the heap, and the address of the object doesn’t change
First deep copy: passJSON
Two of the API
- The json.parse () method parses JSON strings to construct JavaScript values or objects described by the strings
- The json.stringify () method converts a JavaScript value (object or array) to a JSON string
There’s a really neat way to implement deep copy in JavaScript — json.stringify,
let obj = {
name: "yayxs".fav: [{type: "play"}].friend: {
name: "wanghuahua"}};const objStr = JSON.stringify(obj) // deepClone.js:16 {"name":"yayxs","fav":[{"type":"play"}],"friend":{"name":"wanghuahua"}}
const objCopy = JSON.parse(objStr)
objCopy.fav.splice(0.1)
console.log(obj['fav']) / / ({})
console.log(objCopy['fav']) / / []
Copy the code
But if the individual elements are functions, let’s try it
let fnArr = [
() = >{
console.log(1)},() = >{
console.log(2)}]console.log(JSON.parse(JSON.stringify(fnArr))); // [null, null]
Copy the code
Second deep copy: recursive copy
Determine the type of the property value, when the current property value type is an object, and then recursively clone,
function firstDeepClone(target){
// If it is a value type or null, return directly
if(typeoftarget ! = ='object' ||target===null ) {
return target
}
// Result object
let res = target instanceof Array ? [] : {};
for(let key in res){
if(obj.hasOwnProperty(key)){
// Check whether the attribute value corresponding to the current key is a reference type
if(typeof obj[key] === 'object'){
res[key] = firstDeepClone(obj[key])
}else{
res[key] = obj[key]
}
}
}
}
Copy the code
Implement the New operator in JavaScript by hand
Extended interview questions
Do you have a lot of question marks
- Question1: What did New do after that?
- Can I write the principle of the new operator?
- Q3: What is the difference between creating objects with new and creating objects with literals
MDN description of the new operator keyword
- Create an empty simple JavaScript object (i.e
{}
);- Link this object (that is, set its constructor) to another object;
- Take the object created in Step 1 as the object
this
Context;- Returns if the function does not return an object
this
.
The above four articles are about the new operator (or keyword) on MDN. It is a simple experience to use the constructor to new an object
function Person(name, age) {
console.log("this".this);
this.name = name;
this.age = age;
}
// Then add the prototype method ** to the ** constructor
Person.prototype.height = 180;
Person.prototype.sayName = function() {
console.log(this.name);
};
let p = new Person("yayxs".20);
console.log(p.name); // yayxs
console.log(p.age);
20;
p.sayName(); // yayxs
console.log(p.__proto__ === Person.prototype); // The stereotype property of object P (instance) points to the stereotype of the constructor,
Copy the code
Now that we’re customizing it, we’ll use it in much the same way as new.
// ------ when using new
const p = myNew Person('yayxs'.20) // The result is an object
// ---------
Copy the code
The first version of myNew
The idea is to declare an object, take the current constructor and its parameters, have the new object’s prototype attribute point to the constructor’s prototype, and then call the constructor, passing in the object’s parameters
function myNew() {
let obj = new Object(),constructor.args] = [...arguments];
obj.__proto__ = constructor.prototype;
constructor.apply(obj, args);
return obj;
}
Copy the code
The second edition of myNew
As can be seen from the simple case mentioned above,
-
New A constructor returns an object whose stereotype property (that is, ** proto **) is congruent with the constructor’s stereotype
-
The instance created by new through the constructor Persion has access to properties in the constructor, like this
console.log(xiaoMing.name); / / xiao Ming Copy the code
-
To the point: Instance objects from new are linked by a prototype chain and a constructor
A constructor is basically a function, and a function can have a return value
function Person(name) {
this.name = name;
// return 1; // Returns the internally created object
// return "1"; // Returns the internally created object
// return null; // Returns the internally created object
// return undefined; // Returns the internally created object
// return {}; // {} // returns directly
return function() {}; // Return directly
return [1]; // [1] // Returns directly
}
let p = new Person("Bill");
console.log(p);
Copy the code
Given the worthwhile idea of returning a constructor, test it out with different data types
- Different data types return different effects, like the number 1 string “1”, which still returns an internally created object
- So if you return an object ({}) or an array ([]), it will be returned directly
summary
That is, constructors generally do not need a return
- Return a generic datatype. It doesn’t work
- So let’s return an object. What’s the point of new
function myNew(){
let obj = new Object(),constructor.args] = [...arguments]
obj.__proto__ = constructor.prototype;
let res = constructor.apply(obj,args)
return = typeof res= = = 'object'?res : obj;
}
Copy the code
Write your own myNew summary
If you implement a new yourself, you must first satisfy several of its effects
-
A constructor that returns an object should have an object in it
let obj = {}; Copy the code
-
And points its __proto__ attribute to the constructor’s Prototype attribute
obj.__proto__ = constructor.prototype; Copy the code
-
Call the constructor to bind this
constructor.apply(obj, args); Copy the code
-
The original value should be ignored, and the returned object should be processed normally
res instanceof Object ? res : obj; Copy the code
Arrow function usingnew
var Foo = () = > {};
var foo = new Foo(); // TypeError: Foo is not a constructor
Copy the code
- Cannot be used as constructors, that is, not used
new
Command, otherwise an error will be thrown
this
Pointing is fixed, not because there is a binding inside the arrow functionthis
The actual reason for this is that arrow functions don’t have their ownthis
Lead to internalthis
That’s the outer code blockthis
. Precisely because it doesn’tthis
, so it cannot be used as a constructor.
Handwriting implementation of call and apply
preface
Functions can be passed, used as objects, etc. Let’s look at a bit of code. The function passes the call to the original method, but the context this is missing, which leads to our call() method. Call is just a built-in function method. The method used is add.call(), and the add function automatically executes output 3
// The context parameter specifies the this value
// arg1 argument one
// arg2 argument two
func.call(context, arg1, arg2, ...)
Copy the code
function add(a, b) {
console.log("Add this".this);
console.log(a + b);
}
add(1.2); // This points to window
add.call({ name: "yayxs" }, 1.2); // this points to {name:'yayxs'}
Copy the code
Implement the first version of Call
At this point we pull out the incoming object
let o = {
name: "yayxs"};function sayName() {
console.log(this.name);
}
sayName.call(o); // yayxs
Copy the code
Function.prototype.myCall = function(ctx) {
console.log(this) // This is the sayName function
console.log(ctx) // {name: "yayxs"}
ctx.tempFunc = this
ctx.tempFunc()
delete ctx.tempFunc
};
sayName.myCall(o,'Parameter one'.'Parameter two') // Theoretically output yayxs
Copy the code
Implement call version 2
Parameters 1 and 2 in myCall are not participatory
Function.prototype.myCall = function(ctx) {
console.log(this) // This is the sayName function
console.log(ctx) // {name: "yayxs"}
console.log('arguments'.arguments)
let tempArgs = [];// Use it to store parameters
for(let i=1,len=arguments.length; i<len; i++){console.log(arguments[i]) // First loop body output parameter 1 second loop body parameter 2
tempArgs.push('arguments[' + i + '] ');
}
console.log(tempArgs);
ctx.tempFunc = this
// ctx.tempFunc()
let evalScript = 'ctx.tempFunc(' + tempArgs +') '
eval(evalScript);
delete ctx.tempFunc
};
Copy the code
Implement Apply manually
// ---------------- implement myApply
Function.prototype.myApply = function(ctx,arr){
ctx.tempFunc = this
let result
if(! arr){ result = ctx.tempFunc()// Execute directly
}else{
let args = []
for (let i = 0, len = arr.length; i < len; i++) {
args.push('arr[' + i + '] ');
}
result = eval('ctx.tempFunc(' + args + ') ')}delete ctx.tempFunc
return result
}
Copy the code
conclusion
In general, the call Apply function is used to change the direction of this. At present, js still exists the phenomenon of callback function, especially in the framework of some asynchronous callback is also very common, it is inevitable that this will get lost both different and similar, if their own handwritten code to implement call and apply
- Gets the bound function
- The bound function appends to the hijacked replacement object
- The bound function appends to the hijacked replacement object
The method name | role | Automatic execution | The list of parameters |
---|---|---|---|
call | Change the direction of this | Autoexecute function | General list |
apply | Change the direction of this | Autoexecute function | An array |
Implement bind by hand
Before we implement bind by hand, let’s remind ourselves of how bind works. Let’s say that in the React framework,
class App extends React.Component {
constructor() {
super(a);this.state = {
num: 0}; }// 1 synthesizes the setState in the event
handleClick() {
console.log(this.state);
this.setState({ num: this.state.num + 1 }); // State is not updated after the synthesis event is completed, resulting in the so-called asynchronous try block
console.log(this.state);
}
componentDidUpdate() {
console.log(this.state.num);
}
render() {
return (
<>{this.state.num} // You can see that we use the bind function to bind this<button onClick={this.handleClick.bind(this)}>button</button>
</>); }}export default App;
Copy the code
The bind() method creates a new function. When bind() is called, this of the new function is specified as the first argument to bind(), and the remaining arguments are used as arguments to the new function. But we need to mention in advance that bind needs Polyfill. Because most browsers implement the built-in function.prototype. bind implementation, some don’t
const user = {
name:'yayxs',}function showYourself(){
console.log(this.name)
}
const result = showYourself.bind(user)
Copy the code
The first bind
const user = {
name: "yayxs"};function showYourself(sex) {
console.log(this.name);
console.log(sex)
}
let resultFn;
resultFn = showYourself.bind(user);
// console.log(resultFn)
Function.prototype.myFirstBind = function(ctx) {
console.log(ctx); // user {name:'yayxs'}
let _this = this;
// The first step returns a function
return function() {
// _this is the showYourself function
return _this.apply(ctx);
};
};
resultFn = showYourself.myFirstBind(user);
// console.log(resultFn)
Copy the code
The second bind
Function.prototype.secBind = function() {
let self = this.// Save the original function
context = [].shift.call(arguments); // The context of this to bind
args = [].slice.call(arguments); // The remaining parameters are converted to arrays
return function() {
// Return a new function
// It's going to execute the new function using the previously passed context as the this in the new function. It's going to combine the UN parameters twice as its parameters
return self.apply(context, [].concat.call(args, [].slice.call(arguments)));
};
};
Copy the code
Handwriting implementation of string.prototpye.trim () method
ECMAScript provides the trim() method on all strings. This method creates a copy of the string, removes all preceding and following Spaces, and returns the result. Since trim() returns a copy of the string, the original string is unaffected, meaning that the original pre-and post-whitespace characters are preserved.
To simplify substring substitution, ECMAScript provides the replace() method. This method takes two arguments. The first argument can be a RegExp object or a string (which is not converted to a regular expression), and the second argument can be a string or a function. If the first argument is a string, only the first substring is replaced. To replace all substrings, the first argument must be a regular expression with a global tag,
The method of clearing Spaces on both sides of a string with replace and the re preserves the Spaces on both sides and clears the Spaces inside
String.prototype.trim
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/gm.' '); }}Copy the code
Handwriting implementation of EventBus/EventEmitter
/ / eventBus. Js file
import Vue from "vue";
const EventBus = new Vue(); // Is essentially a Vue instance
export default EventBus;
Copy the code
// main.js
import EventBus from "eventBus.js";
Vue.prototype.EventBus = EventBus;
Copy the code
// Send events
this.$EventBus.$emit("sendVal"."Event issuing");
// Listen on events
this.$EventBus.$on("sendVal".(val) = > {
console.log(val);
});
Copy the code
class EventEmitter {
constructor() {
this.handles = new Map(a);// Store the relationship between practice callbacks
}
on(evtName, cb) {
if (!this.handles.has(evtName)) {
this.handles.set(evtName, []);
}
this.handles[evtName].push(cb);
}
emit(evtName, ... args) {
if (this.handles.has(evtName)) {
for (let i = 0, len = this.handles[evtName].length; i < len; i++) {
this.handles[evtName][cb](... args); }}}off(evtName, cb) {
const cbs = this.handles[evtName];
const idx = cbs.indexOf(cb);
if(idx ! = = -1) {
cbs.splice(idx, 1); }}once(evtName, cb) {
const warp = (. args) = >{ cb(... args);this.off(evtName, warp);
};
this.on(evtName, warp); }}Copy the code
Handwritten array to achieve the method of heavy
So the first thing you have to do to figure out how to do this is, what is a repeating element
/** * When it comes to array de-duplication, the first thing to do is to have an array */
// First step
console.log(1= = =1); // true
console.log("1"= = ="1"); // true
console.log("true"= = ="true"); // true
console.log(false= = =false); // true
console.log(undefined= = =undefined); // true
console.log(null= = =null); // true
console.log(NaN= = =NaN); // false
console.log({} === {}); // false
console.log([] === []); // false
Copy the code
Next step: Prepare the target array with repeating elements
let targetArr = ["1"."1".1.1.true.true.undefined.undefined.null.null];
console.log(targetArr);
Copy the code
Step 3: Write out the method, this is the time to write the method
/** * desc */
function unique1(arr) {
let result = []; // Result array
for (let i = 0, len = arr.length; i < len; i++) {
for (var j = 0, resLen = result.length; j < resLen; j++) {
if (arr[i] === result[j]) {
break; }}if(j === result.length) { result.push(arr[i]); }}return result;
}
Copy the code
/** * desc indexOf */
const unique2 = (arr) = > {
let result = [];
for (let i = 0, len = arr.length; i < len; i++) {
if (result.indexOf(arr[i]) === -1) {
// No element was found in the result arrayresult.push(arr[i]); }}return result;
};
Copy the code
/** * sort */
const unique3 = (target) = > {
target.sort();
let result = [target[0]].// Fetch the first element
for (let i = 1; i < target.length; i++) { target[i] ! == target[i -1] && result.push(target[i]); // The current item is added to the result array if it differs from its predecessor
}
return result;
};
Copy the code
/** * desc The fourth option uses the filter function in conjunction with indexof */
const unique4 = (target) = > {
return target.filter((item, index) = > {
return target.indexOf(item) === index; // The index of the array is the same as the index of the retrieval
});
};
Copy the code
/** * desc the fifth method uses the key-value pair of the object combined with obj.hasownProperty () */
const unique5 = (target) = > {
let obj = {}; // Initialize an empty object
let result = new Array(a); result = target.filter((item, index) = >
// typeof item + item mainly considers that the key value 1 of the object is changed to '1'.
obj.hasOwnProperty(typeof item + item)
? false
: (obj[typeof item + item] = true));return result;
};
Copy the code
/** * desc The sixth option uses ES6's new syntax Set ** /
const unique6 = (target) = > {
The Set object allows you to store a unique value of any type, either a primitive value or an object reference.
let x = new Set(target); // Set { '1', 1, true, null }
return [...x]; // Convert to an array
};
Copy the code
/** * select * from ** /
const unique7 = (target) = > {
The Set object allows you to store a unique value of any type, either a primitive value or an object reference.
let x = new Set(target); // Set { '1', 1, true, null }
return Array.from(x); // Convert to an array
};
Copy the code
/** * desc ** /
const unique8 = (target) = > {
let result = []; // Result array
let hash = {};
for (let ele of target) {
if(! hash[ele]) {// Hash has no elements in the array
result.push(ele); // Put the element in
hash[ele] = true; // The hash is already marked true so that the next loop will not continue to put the same element in the result array}}return result;
};
Copy the code
Desc / * * * 9 * faults hash scheme using the Map types exist in the same key is not to find, but the '1' and 1 is different elements * please test it on its own haha ~ * /
const unique9 = (target) = > {
let map = new Map(a);// Initialize the map
let result = new Array(a);// Initialize the array
for (let i = 0; i < target.length; i++) {
if (map.has(target[i])) {
map.set(target[i], true);
} else {
map.set(target[i], false); result.push(target[i]); }}return result;
};
Copy the code
/** * desc 10 double-layer for loop variant ** */
const unique10 = (target) = > {
// let result = [];
for (let i = 0; i < target.length; i++) {
for (let j = i + 1; j < target.length; j++) {
if (target[i] === target[j]) {
// If two elements are the same, one is removed from the target element
target.splice(j, 1);
// Splice will change the array, so the relevant length should be subtracted by onei--; j--; }}}return target;
};
Copy the code
/** * desc Includes ** */
const unique11 = (target) = > {
let result = [];
for (let ele of target) {
// where ele is each element of each target element! result.includes(ele) && result.push(ele);// If there is no ele in the result array, add it
}
return result;
};
Copy the code
/** * desc reduce ** */
const unique12 = (target) = > {
return target.reduce((previousValue, currentValue, currentIndex) = > {
returnpreviousValue.includes(currentValue) ? previousValue : [...previousValue, currentValue]; } []); };Copy the code
console.log(unique1(targetArr)); // ["1", 1, true, undefined, null]
console.log(unique2(targetArr)); // ["1", 1, true, undefined, null]
console.log(unique3(targetArr)); // ["1", 1, null, true, undefined]
console.log(unique4(targetArr)); // ["1", 1, null, true, undefined]
console.log(unique5(targetArr)); // ["1", 1, null, true, undefined]
Copy the code
Handwritten implementation outputs triangles made up of * signs
/ * * * * * * * 1-1-2 * * * * 3-3 * * * * * * / 4-4
for (let row = 0; row < 4; row++) { / / the number of rows
for (let num = 0; num < row; num++) {
document.write("*");
}
document.write("<br />");
}
for(let row = 4; row>0; row--){for(let num=0; num<row; num++){document.write("*");
}
document.write("<br />");
}
Copy the code
- Author: Yang Xiaoyang
- The code examples above can be found in… /demos/written
- Alternate browsing address…… debounce.html
- reference
- Hu Yu’s blog
- JavaScript Design Patterns and Development Practices
- Thank you for your thumbs up and comments if it helps. What topics would you like to share in the future?