JavaScript Knowledge extension

scope

Scope scope:

1. Definition: the scope within which variable functions or members can be accessed in the entire program;

2. Can also be used for information hiding

Block scope: {… } contains code that is a block scope, JS has no block scope;

Dynamic scope: Whether members of a function can be accessed is determined only at run time

function f(){ alert(x); } function f1(){ var x = 1; f(); } function f2(){ var x = 2; f(); } f1(); // error: x is not defined, indicating that JS has no dynamic scope f2();Copy the code

JS has only static scope lexical scope, also known as lexical scope or closure, which determines the relevant scope at the lexical creation stage. Closure: A function that references a free variable.

function f(){
	var x = 100;
	function g(){
		...
	}
	g();
}
f();

Copy the code
Function f(){// when f() is created, [[scope]] == window //f.[[scope]] == window //f() creates its own lexical context f.le, f.le ->f.[[scope]] F () is just called), f() {x = undefined, g(){... }}, g.[[scope]] == f. F.le {x = 100, g(){... }} function g(){g.[[scope]] == f.le... } g(); / / g () at run time, creates own lexical environment, g.l e - > g. [[scope]] / / in conclusion formed a chain / / g.l e - > g. [[scope]] = = f.l e - > f. window} [[scope]] = = f ();Copy the code

The way that JS creates functions

There are three:

1. Function declaration

function f() {… }

2. Function expressions

var f = function () {… }

Function constructor

Var f = new Function(” parameter “, “Function body”)// Scope created this way always refers to the global, not its parent

closure

, short for lexical closure, is a function that references a free variable. The referenced free variable will exist with the function, even if it has left the environment in which it was created. So, there is another way to say that closures are entities composed of functions and their associated reference environments.

function f1() { var a = 10; var b = 20; Function f2() {// the f2() function is the closure console.log(a); } f2(); } f1();Copy the code

Benefits of closures

1. Reduce global variables

// each time the function add() is called, a increments by 1

function add(){ var a = 0; a++; alert(a); } add(); add(); // Each call to a starts at 0Copy the code
Var a = 0; function add() { a++; alert(a); } add(); add(); // But doing so increases the global variableCopy the code
Function f(){var a = 0; return function(){ a++; alert(a); } } var result = f(); result(); result();Copy the code

2. Reduce the number of arguments passed to the function

// Implement, for example, cardinality 2, maximum number 3, return value 2+ 1+2+3 value

// It can be done this way

function add(base,max){… }

Function calFactory(base){return function(Max){var total = 0; for(var i = 1, i <= max, i++ ){ total +=i; } return total + base; } } var adder = calFactory(2); adder(3); //8//2+1+2+3 adder(4); / / 12 / / 2 + 1 + 2 + 3 + 4Copy the code

3. Play the role of encapsulation

(function(){ var m = 0; Function getM(){return m; } function setM(){// m = val; } window.g = getM; // Interface window.s = setM; }) (); // Immediately called anonymous function s(12); alert(g());Copy the code

Closure considerations:

1. Captured variables are drinkable, not copied

function f(){ var num = 1; function g(){ alert(num); // reference parent num} num++; g(); / / 2}Copy the code

2. A different closure is generated each time the parent function is called

function f(){ var num = 1; return function(){ num++; alert(num); } } var result1 = f(); // A new lexical environment is created each time a function is called result1(); //2 result1(); //3 var result2 = f(); // Create a new lexical environment result2(); //2 result2(); / / 3Copy the code

3. Problems in the loop

The < body > < div id = "1" > 1 < / div > < div id = "2" > 2 < / div > < div id = "3" > 3 < / div > for (var I = 1; i <=3; I ++){var ele = document.getelementbyid (" I "); ele.onclick = function(){ alert(i); }} </body> // Click 1, 2, and 3 to pop up 4, because there is no block-level scope, so I equals the global variable // solution, Can use the closure < body > < div id = "1" > 1 < / div > < div id = "2" > 2 < / div > < div id = "3" > 3 < / div > (for (var I = 1; i <=3; I ++){var ele = document.getelementbyid (" I "); ele.onclick = (function(id){ return function(){ alert(id); } })(i); } </body> </body> </body> </body> </body>Copy the code

pseudo-classes

The _ _ proto _ _ object has nothing to do with the function and points directly to the function’s prototype

// Functions have prototype attributes. Objects have _ _ proto _ _. Functions are also objects, so functions have prototype attributes

function Person(){ var age = 30; this.age = 22; This. Name = "nice"; } Person.prototype.headCount = 1; var p = new Person(); Person() has age and name attributes inside p. P can also refer to // person.protpType via __proto__. P has nothing to do with Person(). Person. The prototype = {xx: xx "} "; // Rewrite Person's prototype completely from console.log(p.x); //undefined// now p can't fetch the new Person. Prototype console.log(p.hadcount); //1// But the Person. Prototype to which the original p.__proto__ refers still existsCopy the code

this

This always refers to an object

This can be written directly inside the global object and always refers to the window object; This can also be written inside a function, where there are three situations:

The first case:

Var ele = document. GetElementById (" id "); Ele. AddElementListener (" click ", the function {the console. The log (this); // In this case this always refers to the object that raised the event ele})Copy the code

The second case:

// This refers to a run-time decision, not a code-time decision

// This refers to whoever the runtime function is called by

Var o = {name: "nice"; print:function(){ console.log(this.name); } } o.print(); //cj// the function is called by o var ff = o.print; ff(); //undefined// this is equivalent to window.ff(), which is called by windowCopy the code

The third case:

Function f(){this.name = "nice"; }Copy the code

The second case above changes the pointing of this, and you can also change the pointing of this using call or apply or bind, which are all things that function objects have

The difference between call and apply:

Call passes arguments as a list of arguments, one by one, while Apply passes arguments as an array

Var o = {name: "nice"; print:function(){ console.log(this.name); } } var ff = o.print; ff(); / / undefined enclosing name = "global"; this.age = 22; ff(); //global function log(a,b){ console.log(this[a]); console.log(this[b]); } the log (" name ", "age"); / / global 22 the call (o, "name"); / / nice / / change this point, the equivalent of o.l og (" name ") the call (o, "name", "age"); Log. apply(o,[' name ', 'age'])//nice undefined//undefined because there is no age variable in the o object log.apply(o,[' name ', 'age'])//nice undefinedCopy the code

New Custom implementation

function Person(name, age){ this.name = name; this.age = age; } var p1 = new Person(" cj ", 22); console.log(p1.name); / / "cj" console. The log (p1) age); / / 22Copy the code

The implementation writes a new as in the previous example

Function New(f){return function(){New Person() var o = {" __proto__ ":f.prototype}; f.apply(o,arguments); return o; }} var p2 = New(Person)(" xx ",33); console.log(p2.name); / / "xx" console. The log (p2) age); //33 console.log(p2 instanceof Person); / / true Person. Prototype. Xx = "aaaa"; console.log(p2.xx); / / "aaaa"Copy the code

encapsulation

function Person (){ var age = 100; Function PM (){// Console.log (" private method "); } this.name = name; This.text = function(){console.log(" public method "); }}Copy the code

// The code above does not make sense. It should be written in the following way

function Person (){ var age = 100; function pm(){ console.log(this.name); } this.name = name; This.text = function(){console.log(" public method "); pm(); }} var p1 = new Person(" cj "); console.log(p1.text()); //public method undefined // Call PM () in window because PM () has no prefix. // Change code PM () to pm.call(this)Copy the code

// Or use object factories to handle public and private calls to each other

function Person(pname){ function pm(){ console.log(self.name); } var self = { name:pname; test:function(){ pm(); }}; return self; } var p2 = Person(" cj "); console.log(p2.test()); / / "cj"Copy the code

inheritance

Shallow copy

Var person = {name: "cj"; age:22; } var programmer = {language: "Javascript"; } function extend(p, c){ var c = c||{}; for(var prop in p){ c[prop] = p[prop]; } return c; } extend(person, programmer) {} extend(person, programmer) {} extend(person, programmer) {Copy the code
Var person = {name: "cj"; age:22; Address: {home: "home address"; Office: office "address"; }} var programmer = {language: "Javascript"; } function extend(p, c){ var c = c||{}; for(var prop in p){ c[prop] = p[prop]; } return c; } extend(person, programmer) console.log(programmer. Name);} extend(person, programmer) console.log(programmer. / / programmer. "cj" name = "nice"; console.log(person.name); // "cj" // shallow copy, variable value changes console.log(programmer. Name); / / "nice" programmer. Address. Home = "Shenzhen"; console.log(programmer.address.home); / / "Shenzhen" console. The log (person. Address. Home); // "Shenzhen" // the child changes the parent value, indicating only a shallow copy // the child and the parent reference point to the same location // array and object, can have this problem // array can also be iterated with a for in loopCopy the code

Deep copy

Inheritance of the formal implementation of an object argument

function extendDeeply(p, c){ var c =c||{}; For (var prop in p){if(typrof p[prop] === "object"){c[prop] = (p.[prop]. Constructor === Array)? [] : {}; extendDeeply(p[prop], c[prop]); }else{ c[prop] = p[prop]; }}}Copy the code

Implement inheritance in the form of constructors

Function Parent(){// Parent object this.name = "ABC"; This. The address = {home: "home"}; } function Child(){parent.call (this); // Copy this.language = "js" with call form; } c = new Child(); console.log(c.name); // "ABC" P = new Parent(); C.a. ddress. Home = "Shenzhen" console. The log (p.a ddress. Home); // "home" // Is a deep copyCopy the code

Create implementation inheritance

Var p = {name: "cj"}; / / p. __proto__ pointing to the object. The prototype, the object. The prototype. __proto__ point to null function myCreate (p) {var ins. function F(){}; F.prototype = p; ins = new F(); return ins; } var c = myCreate(p); // The system's own object.create (p); console.log(c.name); / / "cj"Copy the code

The code above has its own object.create ()

Attributes can also be enhanced, for example

var c2 = Object.create(p,{age:{value:20},salary:{value:1000000}}); //p is inherited by the parent class, and console.log(name) is enhanced by the subclass; / / "cj" console. The log (age). / / 20Copy the code

Talk about instanceof

Objects on the left, functions on the right

var f = new F(); console.log(f instanceof F); //true// if f.constructor == F console.log(F instanceof Object); __proto__== object.prototype; // if (prototype == Object) {// if (prototype == Object) {// if (prototype == Object) {// if (prototype == ObjectCopy the code

Class inheritance

// Create a parent class

// Create a subclass

// Build relationships

The first way

Function P(){} C(){} C(){} C(){} C(){} C(){} C(){} C(){} C(){ Constructor is P(), so after inheriting the class method, // restore the prototype-type constructor back to c.protoType = C; var c1 = new C(); console.log(c1 instanceof C); //true console.log(c1 instanceof P); / / true C.p rototype. Xx = "xx"; var p1 = new P(); console.log(p.xx); // "xx" // Do not use this way, because the disadvantage is that the son inherits the father, but the son also exposed to the fatherCopy the code

The second way

Function P(){} function C(){}// subclass c.protoType = new P(); var c1 = new C(); console.log(c1 instanceof C); //true console.log(c1 instanceof P); / / true C.p rototype. Xx = "xx"; var p1 = new P(); console.log(p.xx); // use undefined // advantage: the child will not be exposed to the parent // disadvantage: there is a layer in the middle of the search, and the new P is not useful, just play a bridge between the child and the parentCopy the code

The third form

Function P(){} function C(){}// function F(); F.prototype = P.prototype; var f = new F(); C.prototype = f; C. protoType = object.create (p.prototype); // The advantage is that there is only a new empty function in the middle, which does not have the disadvantages mentioned aboveCopy the code

Class inheritance tetralogy:

1 Create a parent class and add attributes and methods of the parent class

2 Creating subclasses

3 Immediate Inheritance

Inheritance is implemented above, but you should instinctively correct the constructor of a subclass’s prototype back into the subclass’s constructor

4 add the attributes of the subclass,

By reversing 3 and 4, and inheriting with an equal sign, you rewrite your subclass exactly like its parent class

/ / for

Function Person () {} / / create a superclass Person. The prototype. The headCount = 1; Person.prototype.eat = function(){// Add console.log(" eating... ); Prototype = object.create (Person. Prototype); / / to inherit a Programmer. The prototype. The constructor = Programmer; / / to amend the subclass constructor of the prototype back (instinct) a Programmer. Prototype. Language = "Javascript"; / / add a subclass properties Programmer. The prototype. The work = function () {/ / add a subclass methods console. The log (" I am writing code in "+ this. Language); } var js = new Programmer(); console.log(js.eat()); //eating... console.log(js.language); / / js. "Javascript" language = "js"; console.log(js.language); / / "JS" console. The log (JS. The work ()); //i am writing code in JSCopy the code

You can also change the existing code above (with a in the comment) to the code below

createEx(Programmer, Person); . function createEx(Child, Parent){ function F(){}; F.prototype = P.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; }Copy the code
Function Person(name, age){this.name = name; This. Age = age; } Person.prototype.headCount = 1; Person.prototype.eat = function(){// Add console.log(" eating... ); } function Programmer(name, age, title){// Create subclass Person. Apply (this, arguments); Aaaa} createEx(Programmer, Person); Programmer. Prototype. Language = "Javascript"; / / add a subclass properties Programmer. The prototype. The work = function () {/ / add a subclass methods console. The log (" I am writing code in "+ this. Language); } function createEx(Child, Parent){ function F(){}; F.prototype = P.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; } var person = new person (" cj ", 20); console.log(person.name); // "cj" var p = new Programmer(" nice ", 22, "coder"); console.log(p.name); // "nice" person.name = "haha" console.log(" p.name "); // "nice" // no impactCopy the code

Sometimes we’ll call something from the parent inside the child, using super or base

Function Person(name, age){this.name = name; this.age = age; } Person.prototype.headCount = 1; Person.prototype.eat = function(){// Add console.log(" eating... ); } function Programmer(name, age, title){// Create subclass Person. Apply (this, arguments); } createEx(Programmer, Person); Programmer. Prototype. Language = "Javascript"; / / add a subclass properties Programmer. The prototype. The work = function () {/ / add a subclass methods console. The log (" I am writing code in "+ this. Language); Programmer.base.eat(); } function createEx(Child, Parent){function F(){}; F.prototype = P.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.super = Child.base = Parent.prototype; / / * * * * new statements} var csharp = new (" cj ", 22, "the teacher"); console.log(csharp.name); / / "cj" console. The log (csharp. The work ()); //i am writing code in Javascript //eating...Copy the code

polymorphism

have

function F(){}; var f = new F(); The cash-strapped ame = "cj"; The console. The log (f.h asOwnProperty (" name ")); //true// If f.prototype. age = 22; The console. The log (f.h asOwnProperty (" age ")); //false//f Object and prototype Object are two objects that do not have console.log(object.hasownProperty (f, "name")); / / false / / don't use, because is the object level hasOwnPorperty console. The log (F.p rototype. IsPrototypeOf (f)); //true// whether... The prototype of the console. The log (Object. GetPrototypeOf (f)); //F{}//Copy the code

Method overloading

Compile-time polymorphism, typically represented by method overloading, is determined at compile time

Methods with the same name are not allowed in JS; the latter overrides the former

Arguments, the number of arguments to a function

fucntion demo(a, b){ console.log(demo.length); Console. log(arguments.length); // Number of parameters console.log(arguments.length); // The number of arguments}Copy the code

Variable length overloading

function add(){ var total = 0; for(var i = arguments.length - 1; i >= 0; I -) {total + = the arguments [I]; } return total; } console.log(add(1)); //1 console.log(add(1, 2)); / / 3Copy the code

The number of parameters is different

Function fontSize(){var ele = document.getelementbyid (" js "); if(arguments.length == 0){ return ele.style.fontSize; }else{ ele.style.fontSize = arguments[0]; } } fontSize(18); console.log(fontSize()); / / 18Copy the code

Parameter types are different

Function setting(){var ele = document.getelementbyId (" js "); If (typeof arguments[0] === "object"){for(p in arguments[0]){ele. Style [p] = arguments[0][p]; }else{ ele.style.fontSize = arguments[0]; ele.style.backgroundColor = arguments[1]; }} setting (18, "red"); / / setting ({fontSize: 28, backgroundColor: "green"});Copy the code

Methods to rewrite

Runtime polymorphism: overwrite

The following example is one of them

function demo(o){ o.run(); } var o = {run:function(){console.log(" o is running... ); }}; demo(o); //o is running... Var p = {run:function(){console.log(" p is running... ); }}; demo(p); //p is running... // According to the characteristics of the prototype chain, override the same method as the constructor on the instance, using its own methodCopy the code
var f = new F(); F.p rototype. Run = function () {coslole. Log (" FFF "); } f.run(); / / FFF f.r UN = function () {/ / rewrite the console log (" FFF "); } f.run(); F run = function(){console.log(" FFFF "); F.prototype.run(); } f.run(); //ffff //FFFCopy the code

Other situations

Function Parent(){this.run = function(){console.log(" Parent is running "); } } function Child(){ Parent.call(this); Var parentRun = this.run; This.run = function(){// Subclasses override the run method console.log(" child is running "); parentRun(); }} var c = new Child(); c.run(); //child is running //parent is runningCopy the code

Other situations

Function Parent(){} Parent. Prototype. run = function(){console.log(" Parent is running "); } Child.prototype = Object.create(Parent.prototype); // inherit child.super = Parent. Prototype; Function Child(){} child.prototype. run = function(){console.log(" Child is running "); Child.super.run(); } var c = new Child(); c.run(); //child is running //parent is runningCopy the code