Recently I read two volumes of You-Dont-Know-JS. In the process of reading, in order to facilitate future indexing and a deeper understanding, and to avoid forgetting, I have made a summary of the more complicated points in each volume, and edited them as follows.
Blog.xiang. tech/post/js-puz…
types & grammer
-
Judge the following results
var s = 'abc'; s[1] = 'B'; console.log(s); var l = new String('abc'); l[1] = 'B'; console.log(l); Copy the code
Strings and their Boxed objects are immutable and cannot modify in place, so all methods of string return a new string without changing themselves.
- You-Dont-Know-JS
-
How to reverse a string?
s.split('').reverse().join('')
-
Plug in, why can’t directly use Array. The prototype. Reverse. Call reverse string (s)?
When an array is reversed, l.everse () changes l itself. As in the first problem, a string cannot change itself.
-
Determine the following results, why this is the case, and how to make the correct comparison?
0.1 + 0.2= = =0.3; 0.8 - 0.6= = =0.2; Copy the code
According to IEEE 754, floating point stores 64 bit double precision, which can represent 2^64 numbers. Floating point is infinite, which means that some floating point numbers must have a loss of precision. 0.1 and 0.2 are represented as binary numbers with a loss of precision. A very small Number is introduced for comparison.EPSILON tolerates error, with a value of 2^-52.
function equal (a, b) { return Math.abs(a - b) < Number.EPSILON } Copy the code
- You-Dont-Know-JS
- zhihu
-
How do I determine if a value is an integer?
// ES6 Number.isInteger(num); // ES5 if (!Number.isInteger) { Number.isInteger = function(num) { return typeof num == "number" && num % 1= =0; }; } Copy the code
- You-Dont-Know-JS#user-content-testing-for-integers
-
How do you tell if a value is +0?
function isPosZero (n) { return n === 0 && 1 / n === Infinity } Copy the code
-
‘ABC’ is primitive value in ‘ABC’.toupperCase (). How do I access the toUpperCase method
When the Primitive Value accesses a property or method, it automatically translates to its wrapper object. You can also use Object.prototype.valueof () Unboxing.
- You-Dont-Know-JS#user-content-boxing-wrappers
-
Determine the following results (Boxing Wrappers)
function foo() { console.log(this) } foo.call(3); Copy the code
Number (3). The reasons are as above.
-
Judge the following results
Array.isArray(Array.prototype) Copy the code
True The prototype of the built-in object is not pure, for example, date. prototype is Date and set. prototype is Set.
- You-Dont-Know-JS#user-content-native-prototypes
-
Judge the following results
Boolean(new Boolean(false)); Boolean(document.all); [] = =' '; [3] = =3; [] = =false; 42= =true; Copy the code
New Boolean() returns object, true document.all, Falsy value is a value that is forced to be false. Everything else will be converted to true
- undefined
- null
- false
- +0, -0, and NaN
- “”
You-Dont-Know-JS#user-content-toboolean
-
Identify the following code issues (TDZ)
var a = 3; let a; Copy the code
This is a Temporal Dead Zone problem, you cannot use A until let A is declared.
-
Identify the following code issues (TDZ)
var x = 3; function foo (x=x) { // .. } foo() Copy the code
Also, in the function default arguments, there is TDZ.
scope & closures
-
What does Engine, Scope, and Compiler do in var a = 2
-
Determine the following results (Lexical Scope)
var scope = 'global scope'; function checkScope () { var scope = 'local scope'; function f() { return scope; } return f; } checkScope()(); Copy the code
‘local scope’
Since JS is a Lexical Scope, a variable is accessed in the current Scope first and, if not, in the nested Scope until it is found. If not, ReferenceError is reported.
-
Judge the following results (as follows)
console.log(a); var a = 3; Copy the code
undefined
The above code is interpreted by the compiler as
var a; console.log(a); a = 3; Copy the code
-
Judge the following results (Function First)
var foo = 1; function foo () {}console.log(foo); Copy the code
1. Functions are also promoted, so they are overridden by assignments.
-
Judge the following results (IIFE & Function First)
var foo = 1; (function () { foo = 2; function foo () {} console.log(foo); }) ()console.log(foo); Copy the code
2, 1
The above code is interpreted by the compiler as follows
var foo = 1; (function () { var foo; function foo () { } foo = 2; console.log(foo); }) ()console.log(foo); Copy the code
-
Determine the following results and how to output in order (Closure)
for (var i = 0; i < 10; i++) { setTimeout(function () { console.log(i); }, 1000)}Copy the code
After about 1s, output 10 10s in a row. Since there is no block-level scope, you can either change var to let or wrap setTimeout with a layer of IIFE.
this & object prototypes
Note: the following are in a browser environment
-
Determine the following results (Default Binding)
function foo() { "use strict"; console.log( this.a ); } var a = 2; foo(); Copy the code
An error is reported, in strict mode of the function, where this is bound to undefined by default.
-
Judge the following results
"use strict"; var a = 2; let b = 3; console.log(this.a, this.b); Copy the code
2, undefined
In the browser environment, this points to the window, and the variable declared by var is attached to the window. Variables declared by the let do not hang on the window.
-
Determine the following result (Strict Mode & Default Binding)
function foo() { console.log( this.a ); } var a = 2; (function(){ "use strict"; foo(); }) ();Copy the code
2
The only function that sets strict mode is this, which is undefined. So it will output normally.
-
Determine the following results (Hard Binding)
function foo () { console.log(this.a); } const o1 = { a: 3 }; const o2 = { a: 4 }; foo.bind(o1).bind(o2)(); Copy the code
3
Bind is a hard binding. This cannot be bound again after the first binding.
-
How to realize the Function. The prototype. The bind and the Function. The prototype. SoftBind
Bind is a hard bind, and softBind can bind this multiple times. The approximate implementation code is as follows. The second argument to bind presets function arguments, so bind is also a partial function. Bind also needs to consider the case of new. But the following example focuses on the differences between hard and soft binding.
Function.prototype.fakeBind = function (obj) { var self = this; return function () { self.call(obj); }}Function.prototype.softBind = function(obj) { var self = this; return function () { self.call(this= = =window? obj : this); }};Copy the code
-
What happens in the process of new, judge the following results (new)
function F () { this.a = 3; return { a: 4; }}const f = new F(); console.log(f.a); Copy the code
4
The process of new is roughly as follows
- Create a new object
- This points to the instance and executes the function
- If no explicit return is made, the instance is returned by default
Because the function explicitly returns an object at the end, it prints 4
-
What are data descriptor and Accessor Descriptor
Both are defined via Object.defineProperty() and have two public key values
- Specifies whether this key can be deleted
- Enumerable specifies whether it can be iterated
Data descriptors have the following key values
- Writable Indicates whether the key can be changed
- value
The accessor descriptor has the following key values
- set
- Get Alternatively, accessor descriptors can be represented as literals
const obj = { get a() {}, set a(val) {} } Copy the code
The internal principle of computed in Vue is GET, and that of watch is SET
-
How do I access properties of an object? ([[Get]])
Accessing an object’s properties triggers the [[Get]] operation, which is briefly described below
- If yes, check the return value of the interceptor. If no, go to the next step
- Check its own properties, if not found proceed to the next step
- If it is not found, it looks up the prototype chain; if not, it returns undefined
The search process is similar to the Scope search for variables, except that the object attribute cannot be found and undefined is returned, while Reference Error is reported when the variable cannot be found.
-
How to assign an attribute to an object ([[Put]])
Assigning an attribute to an object triggers the [[Put]] operation, as outlined below
- Check whether it is blocked by the Proxy
- If the object property is its own property (obj.hasownProperty (‘a’) === true)
- If the property is an access descriptor, the setter function is called
- If the property is a data descriptor, check whether writable is writable
- Normal attribute, direct assignment
- If the object property exists on the stereotype chain
- If the property is an access descriptor, the setter function is called
- If the property is a data descriptor, check whether writable is writable. If writable, overridden by its own attribute, otherwise an error is reported in strict mode
- Common attributes overridden by their own attributes
- If the object does not exist on the prototype chain, assign a value to its property directly
-
How to traverse an object (? iterator)
Set the Symbol. Iterator property to the object
-
How to Implement an inheritance (Object.create & Call)
In the ES6 era, it’s easy to implement inheritance through class & extends. In the ES5 era, we use the following method
function A () {} function B () { A.call(this) } B.prototype = Object.create(A.prototype) // b.protoType = new A() not recommended Copy the code
-
How to implement Object.create
As for why new is not recommended for inheritance, the reason is that you can hardly guarantee that A is A pure function, for example, it will have its own attributes, it may manipulate the DOM, etc. Here is a simple version of the implementation, omitting the second argument.
Object.create = function (o) { function F() {} F.prototype = o; return new F(); } Copy the code
Pay attention to the public number shanyuexixing, record my technical growth, welcome to exchange