1.Agent
1. Question: How to define an object that will not be modified or traversed?
-
Define default properties through Object.defineProperty(object, property name, option)
- cannot be modified
- cannot be deleted
- cannot be traversed
Note: The value passed in by Object.Property and the value returned are the same address
-
You can configure the properties
- value: initial value
- writable:true (true allows to be modified)
- enumerable:true (rue is allowed to be traversed)
- configurable:true (rue is allowed to be deleted)
-
Provides two methods, get and set.
- Note: get and set cannot be used together with value and writable. When setting the value of a property to an object, set will be triggered.
// var obj={} var o = Object.defineProperty({<!-- -->}, "name", {<!-- --> value: "Andy Lau",//initial value writable: true,//true allows to be modified enumerable: true,//true is allowed to be traversed configurable: true//true allows to be deleted }) //delete o.name//delete // o.name="Xiaoyi"//Modify // for(let k in o){<!-- --> // console.log(k,o[k]);//name Andy Lau // }//Traverse console.log(o);//{name: 'Andy Lau'} var person = {<!-- --> name: "Wu Yanzu", } //Give an initial value person.age = 0 // Problem: Directly operating Person and adding attributes to Person may lead to inaccurate values. // Hire an agent (secretary) var proxy = Object.defineProperty({<!-- -->}, "age", {<!-- --> set(val) {<!-- --> if (!(val >= 18 & amp; & amp; val <= 50)) {<!-- --> console.log("Illegal value"); } else {<!-- --> console.log("Value is legal"); person.age = val } }, get() {<!-- --> return `Age${<!-- -->person.age} years old` } }) // Reading and writing must go through the proxy proxy.age = 22//Set age console.log(proxy.age);//Read age console.log(person);
2. How many parameters does the viewing method have
Use arguments
3.hasOwnProperty
-
Arrays are special objects that have the properties and methods of the object’s prototype.
-
for…in will traverse the properties and methods on the prototype
solve:
- If you use Object.prototype.hasOwnProperty for properties and methods on the prototype, it will be false, not true.
-
for…of will not iterate over the properties and methods on the prototype
solve:
- Use Object.keys combined with for…of
Object.prototype.address = "China" function Person(name, age, sex) {<!-- --> this.name = name, this.age = age, this.sex = sex } var p = new Person("Xiaoyi", 22, "female") // for..in will traverse to the properties and methods on the parent prototype for (let key in p) {<!-- --> console.log(key);//name, age, sex,address } // Solution 1: Use Object.keys combined with for..of var keys = Object.keys(p) for (let key of keys) {<!-- --> console.log(key);//name, age, sex } // Solution 2: If Object.prototype.hasOwnProperty is a property or method on the prototype, it will be false, not true. for (let key in p) {<!-- --> // If it is a property or method on the prototype, it is false, not true console.log(key,Object.prototype.hasOwnProperty.call(p, key)); if (Object.prototype.hasOwnProperty.call(p, key)) {<!-- --> const el = p[key] console.log(el); } }
4.Shallow copy
1. Concept: Except that the first-level addresses are not shared, the addresses at the second level and above are all shared, which is a shallow copy.
2. Object copy method
- Object.assign()
- {…obj}
3. Shallow copy of array
- […arr]
- arr.slice(0)
- [].concat(arr)
- arr.filter((item)=>item)
- _.clone(arr) lodash method
var Person = {<!-- --> name: "Lao Liu", age: 50, children: {<!-- --> name: "Xiao Liu", age: 20 } } // Shallow copy of object // method 1 // var newPerson=Object.assign({},Person) // Method Two var newPerson = {<!-- --> ...Person } Person.name = "Lao Lao Liu" Person.children.name = "Xiao Xiao Liu" console.log(Person); console.log(newPerson); console.log(newPerson === Person);//false console.log(newPerson.children === Person.children);//true //Array shallow copy var arr = ["00", ["11", 22], {<!-- --> id: 1, name: "aa" }, {<!-- --> id : 2, name: "bb" }] // var arr1=[...arr] // var arr1=arr.slice(0) // var arr1=[].concat(arr) var arr1 = arr.filter(function(item){<!-- --> return item }) arr1[0] = "99" arr1[1][0] = "zzz" console.log(arr1); console.log(arr);
// Use lodash's clone to implement shallow copy, shallow copy of arrays and objects var arr=[11,[22,33],44] var arr1=_.clone(arr) arr[1][0]="zzzz" arr[0]="aaa" console.log(arr); console.log(arr1); var obj={<!-- -->id:1,name:"Andy Lau",children:{<!-- -->id:2,name:"Xiao Xiaoyi"}} var obj1=_.clone(obj) obj.name="zzzz" obj.children.name="ffff" console.log(obj); console.log(obj1);
Usage of 5.lodash
1Copy lodash.js
.https://www.bootcdn.cn/lodash.js/
2. Open the official website and check the documentation
https://www.lodashjs.com/
6. Deep cloning
1. How to determine the reference type?
1.Object.prototype.toString.call(object name)
? 2.constructor.name
2. How to implement deep cloning?
-
provided by js
JSON.stringify and JSON.parse can achieve deep cloning, but methods will be lost
var p=JSON.parse(JSON.stringify(person0))
-
Write it yourself
//------------Write deep clone yourself--------- var person0 = {<!-- --> id: 1, name: "Cai Xukun", children: {<!-- --> id: 11, name: "Xiao Liu" } } console.log(p); function deep(o) {<!-- --> let temp; if (Object.prototype.toString.call(o).includes("Object")) {<!-- --> temp = {<!-- -->} } else if (Object.prototype.toString.call(o).includes("Array")) {<!-- --> temp = [] } for (const key in o) {<!-- --> if (Object.hasOwnProperty.call(o, key)) {<!-- --> // console.log(o[key]); // If it is a reference data type, perform recursion if (typeof o[key] === "object") {<!-- --> temp[key] = deep(o[key]) // console.log(deep(o[key])); } else {<!-- --> // If it is a value type, assign it directly temp[key] = (o[key]) } } } return temp } var person1 = deep(person0) person0.children.name = "jj" // console.log(person0); // console.log(person1); /* Array implementation deep cloning */ var arr0=[11,[22,33],44] var arr1=deep(arr0) arr0[1][0]="hhh" console.log(arr0); console.log(arr1);
-
Use lodash cloneDeep
var person2 = {<!-- --> id: 1, name: "Cai Xukun", children: {<!-- --> id: 11, name: "Xiao Liu" } } var person3 = _.cloneDeep(person2) person2.children.name = "mmmm" console.log(person2); console.log(person3);
7. Closure
1. Concept:
Functions are nested functions. Internal functions can access variables and parameters of external functions. Variables and parameters will not be recycled by the garbage collection mechanism.
2. Benefits of closure
- Reduce pollution of global variables
- Implement caching
3. Three conditions for forming a closure
- function nested function
- Leverage scope (local/global)
- GC (garbage collection mechanism) will not be recycled if it is used (mark and clear method, reference counting method)
4. Advantages of closure
- Save variables so that a variable resides in memory for a long time and will not be released’
// For outer, a is a local variable function outer() {<!-- --> var a=100 // For inner, a is a global variable function inner(){<!-- --> a+10 } return inner } var f=outer() console.log(f);
8. Throttling and anti-shake
Reduce execution frequency and dilute execution times
? Throttle throttle
// throttle throttle var box = document.querySelector(".box") box.onmousemove = throttle(function (e) {<!-- --> console.log(e); console.log(this); console.log(1); }, 100) // throttle page loading execution function throttle(callback, delay = 600) {<!-- --> let start = Date.now() return function (e) {<!-- --> let end = Date.now() if (end - start >= delay) {<!-- --> callback.bind(this)(e) console.log(this); console.log(e); //Rewrite the start time of the mark for start start=end } } }
? Anti-shake debounce
var box = document.querySelector(".box") // Anti-shake debounce box.onmousemove = debounce(function (e) {<!-- --> console.log(e); console.log(this); console.log(1); }, 100) function debounce(callback, delay = 600) {<!-- --> var timer; return function (evt) {<!-- --> let self = this clearTimeout(timer) timer = setTimeout(function () {<!-- --> console.log(this); callback.call(self, evt) // callback.call(self, evt); }, delay) } }
9. Box dragging. (Prototype chain + inheritance + constructor)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .box {<!-- --> width: 100px; height: 100px; background-color: pink; position: absolute; } .boxRed {<!-- --> width: 100px; height: 100px; background-color: red; position: absolute; top: 115px; } .boxYellow {<!-- --> width: 100px; height: 100px; background-color: yellow; position: absolute; top: 300px; } </style> </head> <body> <div class="box"></div> <div class="boxRed"></div> <div class="boxYellow"></div> <script> // Prototype drag function DragBox(cls) {<!-- --> this.el = document.querySelector(cls) } DragBox.prototype = {<!-- --> constructor: DragBox, dragStart() {<!-- --> let self = this this.el.onmousedown = function (e) {<!-- --> let disX = e.offsetX let disY = e.offsetY self.dragIng(disX, disY) self.dragEnd() } }, dragIng(x, y) {<!-- --> let self = this document.onmousemove = function (e) {<!-- --> console.log(this); self.el.style.left = e.pageX - x + "px" self.el.style.top = e.pageY - y + "px" } }, dragEnd() {<!-- --> document.onmouseup = function () {<!-- --> document.onmousemove = document.onmouseup = null } }, } new DragBox(".box").dragStart() // red inheritance function DragBoxLimit(el) {<!-- --> DragBox.call(this, el) } DragBoxLimit.prototype = new DragBox; DragBoxLimit.prototype.dragIng = function (x, y) {<!-- --> let self = this; document.onmousemove = function (e) {<!-- --> let mX = e.pageX - x let mY = e.pageY - y if (mX < 0) {<!-- --> mX=0 } if (mY < 0) {<!-- --> mY = 0 } self.el.style.left = mX + "px" self.el.style.top = mY + "px" } } new DragBoxLimit(".boxRed").dragStart() //yellow inheritance function DragBoxLimitText(el) {<!-- --> DragBox.call(this, el) } DragBoxLimitText.prototype = new DragBox; DragBoxLimitText.prototype.dragIng = function (x, y) {<!-- --> let self = this; document.onmousemove = function (e) {<!-- --> let mX = e.pageX - x let mY = e.pageY - y if (mX < 0) {<!-- --> mX=0 } if (mY < 0) {<!-- --> mY = 0 } self.el.style.left = mX + "px" self.el.style.top = mY + "px" self.el.innerHTML = "top:" + self.el.style.top + "<br>left:" + self.el.style.left } } new DragBoxLimitText(".boxYellow").dragStart() </script> </body> </html>
10. Box drag (class)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .box {<!-- --> width: 100px; height: 100px; background-color: pink; position: absolute; } .boxRed {<!-- --> width: 100px; height: 100px; background-color: red; position: absolute; top: 115px; } .boxYellow {<!-- --> width: 100px; height: 100px; background-color: yellow; position: absolute; top: 300px; } </style> </head> <body> <div class="box"></div> <div class="boxRed"></div> <div class="boxYellow"></div> <script> class box {<!-- --> constructor(el) {<!-- --> this.el = document.querySelector(el) } dragStart() {<!-- --> let self = this this.el.onmousedown = function (e) {<!-- --> let disX = e.pageX-this.el.offsetLeft let disY = e.offsetY self.dragIng(disX, disY) self.dragEnd() } } dragIng(x, y) {<!-- --> let self = this document.onmousemove = function (e) {<!-- --> console.log(this); self.el.style.left = e.pageX - x + "px" self.el.style.top = e.pageY - y + "px" } } dragEnd() {<!-- --> document.onmouseup = function () {<!-- --> document.onmousemove = document.onmouseup = null } } } class yellowBox extends box {<!-- --> constructor(el) {<!-- --> super(el) // this.left=e.pageX-e.offsetX } dragIng(x, y) {<!-- --> let self = this document.onmousemove = function (e) {<!-- --> console.log(this); self.el.style.left = e.pageX - x + "px" self.el.innerHTML = "left:" + self.el.style.left self.el.style.top = e.pageY - y + "px" self.el.innerHTML = "top:" + self.el.style.top + "<br>left:" + self.el.style.left console.log( self.el.style.left); } } } class RedBox extends box {<!-- --> constructor(el) {<!-- --> super(el) // this.left=e.pageX-e.offsetX } dragIng(x, y) {<!-- --> let self = this document.onmousemove = function (e) {<!-- --> console.log(this); let mX = e.pageX - x let mY = e.pageY - y if (mX < 0) {<!-- --> mX=0 } if (mY < 0) {<!-- --> mY = 0 } self.el.style.left = mX + "px" self.el.style.top = mY + "px" } } } var b = new yellowBox(".boxYellow") var p = new box(".box") var r=new RedBox(".boxRed") r.dragStart() b.dragStart() p.dragStart() </script> </body> </html>
11.tab switching
var Main = document.querySelectorAll(".main") for (var i = 0; i < TabItem.length; i + + ) {<!-- --> TabItem[i].onclick = change(i)//change will be executed 4 times // console.log(TabItem[i].onclick); } function change(n) {<!-- --> return function (e) {<!-- --> for (var i = 0; i < TabItem.length; i + + ) {<!-- --> TabItem[i].className = "tab-item" // the picture below Main[i].className = "main" } // e.target.className="tab-item active" this.className = "tab-item active" console.log(this); // the picture below Main[n].className = "main selected" } }