Home > Article > Web Front-end > JavaScript 10,000 words interview summary
This article brings you relevant knowledge about JavaScript, which mainly introduces a summary of some common interview questions. Let’s take a look at them together. I hope it will be helpful to everyone.
[Related recommendations: JavaScript video tutorial, web front-end】
1.1 What data types are there in Js
There are eight data types in JavaScript
Basic data types: Undefined, Null, Boolean, Number, String, Symbol, BigInt.
Complex data type: Object
Symbol and BigInt are new data types in ES6:
Symbol represents unique and immutable after creation data type, which is mainly to solve the problem of possible global variable conflicts.
BigInt is a numeric type of data that can represent integers in any precision format. BigInt can be used to safely store and operate large integers, even if the number exceeds what Number can represent. safe integer range.
1.2 Talk about your understanding of the heap area and stack area
In the operating system, the memory is divided into For the stack area and heap area
#, the stack area memory is automatically allocated and released by the compiler to store function parameter values, local variable values, etc. It operates like a stack in a data structure.
The memory in the heap area is generally allocated and released by the developer. If the developer does not release it, it may be reclaimed by the garbage collection mechanism at the end of the program.
In the data structure:
In the data structure, the access method of data in the stack is first in, last out.
The heap is a priority queue, which is sorted by priority. The priority can be specified according to size.
Data storage method
The original data type is directly stored in a simple data segment in the stack, occupying small space and fixed size , is frequently used data, so it is stored in the stack;
refers to objects whose data type is stored in the heap, which occupies a large space and is not fixed in size. If stored on the stack, it will affect the performance of the program; the reference data type stores a pointer on the stack, which points to the starting address of the entity in the heap. When the interpreter looks for a reference value, it first retrieves its address on the stack and then obtains the entity from the heap.
1.3 What are the methods of data type detection
Then the method of judging the data type can generally be through: typeof, Four commonly used methods: instanceof, constructor, and toString
1.4 What are the ways to judge an array
Make judgments through Object.prototype.toString.call()
Make judgments through the prototype chain
Through the Array of ES6 .isArray() makes a judgment
makes a judgment by instanceof
passes Array.prototype.isPrototypeOf
1.5 The difference between null and undefined
First of all, Undefined and Null are basic data types. These two basic data types have only one value respectively, which are undefined and null.
undefined means undefined, and null means an empty object. Generally, undefined will be returned when a variable is declared but not defined. Null is mainly used to assign values to some variables that may return objects as initialization.
undefined is not a reserved word in JavaScript, which means that you can use undefined as a variable name, but this is very dangerous and will affect the judgment of undefined values. We can obtain safe undefined values through some methods, such as void 0.
When using typeof to judge these two types, Null typing will return "object", which is a historical problem. Returns true when using a double equal sign to compare two types of values, and returns false when using a triple equal sign.
1.6 What is the result of typeof null and why?
The result of typeof null is Object.
In the first version of JavaScript, all values were stored in 32-bit units, and each unit contained a small type tag (1-3 bits) and the actual data of the current value to be stored. Type labels are stored in the low bits of each unit, and there are five data types:
000: object - 当前存储的数据指向一个对象。 1: int - 当前存储的数据是一个 31 位的有符号整数。 010: double - 当前存储的数据指向一个双精度的浮点数。 100: string - 当前存储的数据指向一个字符串。 110: boolean - 当前存储的数据是布尔值。
If the lowest bit is 1, the length of the type label flag is only one bit; if the lowest bit is 0, the length of the type label flag is three bits, providing two additional data types for storage The length of bit.
There are two special data types:
The value of undefined is (-2)30 (a number beyond the range of integers);
The value of null is the machine code NULL pointer (the value of the null pointer is all 0)
That means the type label of null is also 000, which is the same as the type label of Object The same, so it will be judged as Object.
1.7 Why 0.1 0.2 ! == 0.3, how to make them equal (precision is lost)
Computers store data in binary , so when the computer calculates 0.1 0.2, it is actually calculating the binary sum of the two numbers.
There is only one number type in JS: Number. Its implementation follows the IEEE 754 standard and uses a 64-bit fixed length to represent it, which is a standard double double-precision floating point number. In binary scientific notation, the decimal part of a double-precision floating point number can only retain up to 52 digits, plus the previous 1, which actually means retaining 53 significant digits. The remaining ones need to be discarded, following the "0 rounding to 1" principle in principle.
According to this principle, adding the binary numbers of 0.1 and 0.2 and converting them into decimal numbers is: 0.300000000000000004. So the solution to inequality
is to set a margin of error, often called "machine precision". For JavaScript, this value is usually 2-52. In ES6, the Number.EPSILON attribute is provided, and its value is 2-52. You only need to determine whether 0.1 0.2-0.3 is less than Number.EPSILON. If it is less, you can It is judged to be 0.1 0.2 ===0.3
function numberepsilon(arg1,arg2){ return Math.abs(arg1 - arg2) < Number.EPSILON; } console.log(numberepsilon(0.1 + 0.2, 0.3)); // true
1.8 How to obtain a safe undefined value?
Because undefined is an identifier, it can be used and assigned as a variable, but this will affect the normal judgment of undefined. The expression void ___ has no return value, so the result is undefined. void does not change the result of the expression, it just causes the expression to not return a value. So you can use void 0 to get undefined.
1.9 What is the result of typeof NaN?
NaN means "not a number". NaN is a "sentinel value" (sentinel value, a regular value with special purposes), which is used to indicate that the number is in the numeric type. The error condition is "Performing a mathematical operation without success, this is the result returned after failure".
typeof NaN; // "number"
NaN is a special value that is not equal to itself and is the only non-reflexive value. The so-called irreflexive means that NaN is not equal to anyone, including itself, but in NaN! = NaN will return true
1.10 What is the difference between isNaN and Number.isNaN functions?
After the function isNaN receives a parameter, it will try to convert the parameter into a numerical value. Any value that cannot be converted into a numerical value will return true, so if a non-numeric value is passed in, it will also return true. , will affect the judgment of NaN.
The function Number.isNaN will first determine whether the incoming parameter is a number. If it is a number, it will continue to determine whether it is NaN. Data type conversion will not be performed. This method is more accurate for NaN judgment.
1.11 What are the casting rules for the == operator?
For ==, if the types of the two comparison parties are different, type conversion will be performed. If x and y are compared to see if they are the same, the following judgment process will be carried out:
First, it will be judged whether the two types are the same. If they are the same, the sizes of the two will be compared;
If the types are not the same, Type conversion will be performed;
will first determine whether null and undefined are being compared, and if so, it will return true
determine whether the two types are string and number, if so, the characters will be Convert string to number
1 == '1' ↓ 1 == 1
Determine whether one of the parties is boolean. If so, the boolean will be converted into number and then judge.
'1' == true ↓ '1' == 1 ↓ 1 == 1
Determine whether one of the parties is object and the other is string or number. Or symbol, if so, the object will be converted to the original type and then judged
'1' == { name: 'js' } ↓'1' == '[object Object]'
The flow chart is as follows:
1.12 What are the conversion rules for converting other value types into strings?
Null and Undefined types, null is converted to "null", undefined is converted to "undefined",
Boolean type, true is converted to "true", false is converted to "false".
Number type values are converted directly, but those very small and large numbers use exponential form.
Symbol type values are directly converted, but only explicit casts are allowed. Using implicit casts will generate an error.
对普通对象来说,除非自行定义 toString() 方法,否则会调用 toString()(Object.prototype.toString())来返回内部属性 [[Class]] 的值,如"[object Object]"。如果对象有自己的 toString() 方法,字符串化时就会调用该方法并使用其返回值。
1.13. 其他值类型转成数字的转换规则?
Undefined 类型的值转换为 NaN。
Null 类型的值转换为 0。
Boolean 类型的值,true 转换为 1,false 转换为 0。
String 类型的值转换如同使用 Number() 函数进行转换,如果包含非数字值则转换为 NaN,空字符串为 0。
Symbol 类型的值不能转换为数字,会报错。
对象(包括数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型值,则再遵循以上规则将其强制转换为数字。
为了将值转换为相应的基本类型值, 隐式转换会首先检查该值是否有valueOf()方法。如果有并且返回基本类型值,就使用该值进行强制类型转换。如果没有就使用 toString() 的返回值(如果存在)来进行强制类型转换。
如果 valueOf() 和 toString() 均不返回基本类型值,会产生 TypeError 错误。
1.14 其他值类型转成布尔类型的转换规则?
以下这些是假值: undefined 、 null 、 false 、 +0、-0 和 NaN 、 ""
假值的布尔强制类型转换结果为 false。从逻辑上说,假值列表以外的都应该是真值。
1.15. || 和 && 操作符的返回值?
|| 和 && 首先会对第一个操作数执行条件判断,如果其不是布尔值就先强制转换为布尔类型,然后再执行条件判断。
对于 || 来说,如果条件判断结果为 true 就返回第一个操作数的值,如果为 false 就返回第二个操作数的值。
&& 则相反,如果条件判断结果为 true 就返回第二个操作数的值,如果为 false 就返回第一个操作数的值。
|| 和 && 返回它们其中一个操作数的值,而非条件判断的结果
1.16. Object.is() 与比较操作符 “===”、“==” 的区别?
使用双等号(==)进行相等判断时,如果两边的类型不一致,则会进行强制类型转化后再进行比较。
使用三等号(===)进行相等判断时,如果两边的类型不一致时,不会做强制类型准换,直接返回 false。
使用 Object.is 来进行相等判断时,一般情况下和三等号的判断相同,它处理了一些特殊的情况,比如 -0 和 +0 不再相等,两个 NaN 是相等的。
1.17. 什么是 JavaScript 中的包装类型?
在 JavaScript 中,基本类型是没有属性和方法的,但是为了便于操作基本类型的值,在调用基本类型的属性或方法时 JavaScript 会在后台隐式地将基本类型的值转换为对象。如:
const a = "abc"; a.length; // 3
在访问'abc'.length时,JavaScript 将'abc'在后台转换成String('abc'),然后再访问其length属性。
1.18 Js中隐式转换规则
在 if 语句、逻辑语句、数学运算逻辑、== 等情况下都可能出现隐式类型转换。
坑: 判断时, 尽量不要用 = = , 要用 = = = ( 两个等号判断, 如果类型不同, 默认会进行隐式类型转换再比较)
1.19 说说你对this的理解
this是一个在运行时才进行绑定的引用,在不同的情况下它可能会被绑定不同的对象。
1.20 如何判断 this 的指向
第一种是函数调用模式,当一个函数不是一个对象的属性时,直接作为函数来调用时,this 指向全局对象。
第二种是方法调用模式,如果一个函数作为一个对象的方法来调用时,this 指向这个对象。
第三种是构造器调用模式,如果一个函数用 new 调用时,函数执行前会新创建一个对象,this 指向这个新创建的对象。
第四种是 apply 、 call 和 bind 调用模式,这三个方法都可以显示的指定调用函数的 this 指向。其中 apply 方法接收两个参数:一个是 this 绑定的对象,一个是参数数组。call 方法接收的参数,第一个是 this 绑定的对象,后面的其余参数是传入函数执行的参数。也就是说,在使用 call() 方法时,传递给函数的参数必须逐个列举出来。bind 方法通过传入一个对象,返回一个 this 绑定了传入对象的新函数。这个函数的 this 指向除了使用 new 时会被改变,其他情况下都不会改变。
this绑定的优先级
new绑定优先级 > 显示绑定优先级 > 隐式绑定优先级 > 默认绑定优先级
1.21 Map和Object的区别
1.22 说说你对JSON的理解
JSON 是一种基于文本的轻量级的数据交换格式。它可以被任何的编程语言读取和作为数据格式来传递。
在项目开发中,使用 JSON 作为前后端数据交换的方式。在前端通过将一个符合 JSON 格式的数据结构序列化为 JSON 字符串,然后将它传递到后端,后端通过 JSON 格式的字符串解析后生成对应的数据结构,以此来实现前后端数据的一个传递。
因为 JSON 的语法是基于 js 的,因此很容易将 JSON 和 js 中的对象弄混,但是应该注意的是 JSON 和 js 中的对象不是一回事,JSON 中对象格式更加严格,比如说在 JSON 中属性值不能为函数,不能出现 NaN 这样的属性值等,因此大多数的 js 对象是不符合 JSON 对象的格式的。
在 js 中提供了两个函数来实现 js 数据结构和 JSON 格式的转换处理,
JSON.stringify 函数,通过传入一个符合 JSON 格式的数据结构,将其转换为一个 JSON 字符串。如果传入的数据结构不符合 JSON 格式,那么在序列化的时候会对这些值进行对应的特殊处理,使其符合规范。在前端向后端发送数据时,可以调用这个函数将数据对象转化为 JSON 格式的字符串。
JSON.parse() 函数,这个函数用来将 JSON 格式的字符串转换为一个 js 数据结构,如果传入的字符串不是标准的 JSON 格式的字符串的话,将会抛出错误。当从后端接收到 JSON 格式的字符串时,可以通过这个方法来将其解析为一个 js 数据结构,以此来进行数据的访问。
1.222 String和JSON.stringify的区别
console.log(String("abc")); // abc console.log(JSON.stringify("abc")); // "abc" console.log(String({ key: "value" })); // [object Object] console.log(JSON.stringify({ key: "value" })); // {"key":"value"} console.log(String([1, 2, 3])); // 1,2,3 console.log(JSON.stringify([1, 2, 3])); // [1,2,3] const obj = { title: "devpoint", toString() { return "obj"; }, }; console.log(String(obj)); // obj console.log(JSON.stringify(obj)); // {"title":"devpoint"}
当需要将一个数组和一个普通对象转换为字符串时,经常使用JSON.stringify。
如果需要对象的toString方法被重写,则需要使用String()。
在其他情况下,使用String()将变量转换为字符串。
1.23 什么是伪数组(类数组)
一个拥有 length 属性和若干索引属性的对象就可以被称为类数组对象,类数组对象和数组类似,但是不能调用数组的方法。
常见的类数组对象有 arguments 和 DOM 方法的返回结果,还有一个函数也可以被看作是类数组对象,因为它含有 length 属性值,代表可接收的参数个数。
1.24 类数组转换成数组的方法有哪些
常见的类数组转换为数组的方法有这样几种:
通过 call 调用数组的 slice 方法来实现转换
Array.prototype.slice.call(arrayLike);
通过 call 调用数组的 splice 方法来实现转换
Array.prototype.splice.call(arrayLike, 0);
通过 apply 调用数组的 concat 方法来实现转换
Array.prototype.concat.apply([], arrayLike);
通过 Array.from 方法来实现转换
Array.from(arrayLike);
1.25 Unicode、UTF-8、UTF-16、UTF-32的区别?
Unicode 是编码字符集(字符集),而UTF-8、UTF-16、UTF-32是字符集编码(编码规则);
UTF-16 使用变长码元序列的编码方式,相较于定长码元序列的UTF-32算法更复杂,甚至比同样是变长码元序列的UTF-8也更为复杂,因为其引入了独特的代理对这样的代理机制;
UTF-8需要判断每个字节中的开头标志信息,所以如果某个字节在传送过程中出错了,就会导致后面的字节也会解析出错;而UTF-16不会判断开头标志,即使错也只会错一个字符,所以容错能力教强;
如果字符内容全部英文或英文与其他文字混合,但英文占绝大部分,那么用UTF-8就比UTF-16节省了很多空间;而如果字符内容全部是中文这样类似的字符或者混合字符中中文占绝大多数,那么UTF-16就占优势了,可以节省很多空间;
1.26 常见的位运算符有哪些?其计算规则是什么?
现代计算机中数据都是以二进制的形式存储的,即0、1两种状态,计算机对二进制数据进行的运算加减乘除等都是叫位运算,即将符号位共同参与运算的运算。
常见的位运算有以下几种:
1.27 为什么函数的 arguments 参数是类数组而不是数组?如何遍历类数组?
arguments是一个对象,它的属性是从 0 开始依次递增的数字,还有callee和length等属性,与数组相似;但是它却没有数组常见的方法属性,如forEach, reduce等,所以叫它们类数组。
要遍历类数组,有三个方法:
(1)将数组的方法应用到类数组上,这时候就可以使用call和apply方法,如:
function foo(){ Array.prototype.forEach.call(arguments, a => console.log(a)) }
(2)使用Array.from方法将类数组转化成数组:
function foo(){ const arrArgs = Array.from(arguments) arrArgs.forEach(a => console.log(a)) }
(3)使用展开运算符将类数组转化成数组
function foo(){ const arrArgs = [...arguments] arrArgs.forEach(a => console.log(a)) }
1.28 escape、encodeURI、encodeURIComponent 的区别
encodeURI 是对整个 URI 进行转义,将 URI 中的非法字符转换为合法字符,所以对于一些在 URI 中有特殊意义的字符不会进行转义。
encodeURIComponent 是对 URI 的组成部分进行转义,所以一些特殊字符也会得到转义。
escape 和 encodeURI 的作用相同,不过它们对于 unicode 编码为 0xff 之外字符的时候会有区别,escape 是直接在字符的 unicode 编码前加上 %u,而 encodeURI 首先会将字符转换为 UTF-8 的格式,再在每个字节前加上 %。
1.29 什么是尾调用,使用尾调用有什么好处?
尾调用指的是函数的最后一步调用另一个函数。代码执行是基于执行栈的,所以当在一个函数里调用另一个函数时,会保留当前的执行上下文,然后再新建另外一个执行上下文加入栈中。使用尾调用的话,因为已经是函数的最后一步,所以这时可以不必再保留当前的执行上下文,从而节省了内存,这就是尾调用优化。
但是 ES6 的尾调用优化只在严格模式下开启,正常模式是无效的。
1.30 use strict是什么? 它有什么用?
use strict 是一种 ECMAscript5 添加的(严格模式)运行模式,这种模式使得 Javascript 在更严格的条件下运行。设立严格模式的目的如下:
消除 Javascript 语法的不合理、不严谨之处,减少怪异行为;
消除代码运行的不安全之处,保证代码运行的安全;
提高编译器效率,增加运行速度;
为未来新版本的 Javascript 做好铺垫。
区别:
禁止使用 with 语句。
禁止 this 关键字指向全局对象。
对象不能有重名的属性。
1.31 如何判断一个对象是否属于某个类?
第一种方式,使用 instanceof 运算符来判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。
第二种方式,通过对象的 constructor 属性来判断,对象的 constructor 属性指向该对象的构造函数,但是这种方式不是很安全,因为 constructor 属性可以被改写。
第三种方式,如果需要判断的是某个内置的引用类型的话,可以使用 Object.prototype.toString() 方法来打印对象的[[Class]] 属性来进行判断。
1.32 强类型语言和弱类型语言的区别
强类型语言:强类型语言也称为强类型定义语言,是一种总是强制类型定义的语言,要求变量的使用要严格符合定义,所有变量都必须先定义后使用。Java和C++等语言都是强制类型定义的,也就是说,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。例如你有一个整数,如果不显式地进行转换,你不能将其视为一个字符串。
Weakly typed language: A weakly typed language is also called a weakly typed definition language, which is the opposite of a strongly typed definition. JavaScript language is a weakly typed language. Simply understood, it is a language in which variable types can be ignored. For example, JavaScript is weakly typed. In JavaScript, you can concatenate the string '12' and the integer 3 to get the string '123', and forced type conversion will be performed when adding.
Comparison of the two: Strongly typed languages may be slightly inferior to weakly typed languages in speed, but the rigor brought by strongly typed languages can effectively help avoid many errors.
1.33 The difference between interpreted languages and compiled languages
(1) Interpreted languages use a specialized interpreter to interpret the source program line by line Interpreted into platform-specific machine code and executed immediately. The code is dynamically translated and executed line by line by the interpreter when it is executed, rather than being translated before execution. Interpreted languages do not need to be compiled in advance. They directly interpret the source code into machine code and execute it immediately, so as long as a certain platform provides a corresponding interpreter, the program can be run. Its characteristics are summarized as follows
Every time an interpreted language is run, the source code needs to be interpreted into machine code and executed, which is less efficient;
As long as the platform provides the corresponding interpreter, the source code can be run code, so it can facilitate source program transplantation;
JavaScript, Python, etc. are interpreted languages.
(2) Compiled language uses a specialized compiler to compile the high-level language source code into machine code that can be executed by the platform hardware at one time for a specific platform, and packages it into a machine code that can be executed by the platform hardware. Identifies the format of the executable program. Before a program written in a compiled language is executed, a special compilation process is required to compile the source code into a machine language file, such as an exe format file. When running in the future, you can directly use the compilation result, such as running the exe directly. document. Because it only needs to be compiled once and does not need to be compiled when running later, compiled languages have high execution efficiency. Its characteristics are summarized as follows:
is compiled into a platform-related machine language file at one time, and is separated from the development environment when running, with high operating efficiency;
is related to a specific platform and generally cannot be transplanted to other platforms. ;
C, C, etc. are compiled languages.
The main difference between the two is: the former source program can be run on the platform after compilation, while the latter is compiled during operation. Therefore, the former runs fast and the latter has good cross-platform performance.
1.34 The difference between for...in and for...of
for...of is a new traversal method in ES6 that allows Traverse a data structure (array, object, etc.) containing the iterator interface and return the value of each item. The difference from for...in in ES3 is as follows
for...of The traversal obtains the key value of the object, for …in obtains the key name of the object;
for… in will traverse the entire prototype chain of the object, the performance is very poor and is not recommended, while for…of only traverses the current object and does not traverse the prototype chain;
For array traversal, for...in will return all enumerable attributes in the array (including enumerable attributes on the prototype chain), and for...of only returns the attribute value corresponding to the subscript of the array;
Summary: The for...in loop is mainly designed to traverse objects, not suitable for traversing arrays; the for...of loop can be used to traverse arrays, array-like objects, strings, Sets, Maps and Generators object.
1.35 The difference between ajax, axios, and fetch
(1) AJAX Ajax is "AsynchronousJavascriptAndXML" (asynchronous JavaScript and XML), which means A web development technology for creating interactive web applications. It is a technology that can update parts of a web page without reloading the entire web page. Ajax allows web pages to update asynchronously by exchanging a small amount of data with the server in the background. This means that parts of a web page can be updated without reloading the entire page. Traditional web pages (without Ajax) must reload the entire web page if content needs to be updated. Its shortcomings are as follows:
itself is aimed at MVC programming and does not conform to the trend of front-end MVVM
is developed based on native XHR, and the architecture of XHR itself is not Clear
Does not comply with the principle of Separation of Concerns
The configuration and calling methods are very confusing, and the event-based asynchronous model does not friendly.
(2) Fetch fetch is known as a replacement for AJAX. It appeared in ES6 and uses the promise object in ES6. Fetch is designed based on promises. The code structure of Fetch is much simpler than ajax. Fetch is not a further encapsulation of ajax, but native js, which does not use the XMLHttpRequest object.
Advantages of fetch:
The syntax is concise and more semantic
Based on standard Promise implementation and supports async/await
It is more low-level and provides rich APIs (request, response)
It is separated from XHR and is a new implementation method in the ES specification
Disadvantages of fetch:
fetch only reports errors for network requests. 400 and 500 are treated as successful requests. When the server returns 400 and 500 error codes, it will not be rejected. Only when network errors cause the request to fail to be completed, fetch will be rejected.
fetch does not bring cookies by default, you need to add configuration items: fetch(url, {credentials: 'include'})
1.36 What are the array traversal methods
1.37 What is the difference between forEach and map methodsThis method is used When traversing an array, the difference between the two is as follows:
The forEach() method will execute the provided function for each element, and the operation on the data will change the original array. This method has no return value;
The map() method does not change the value of the original array, but returns a new array. The values in the new array are the values of the original array after calling the function;
1.38 Tell us what you think about Qian Understanding of copy and deep copyShallow copy
Shallow copy refers to the creation of new data, which has an exact copy of the original data attribute value
If the attribute is of a basic type, the value of the basic type is copied. If the attribute is a reference type, the memory address is copied
That is, the shallow copy copies one layer, and the deep reference type shares the memory address
Common shallow copy:
If there is a time object in obj, then The result of JSON.stringify and then JSON.parse will be in the form of a string, not an object.
If there is a RegExp in obj, it will be printed as an empty object. If the object If there is a function or undefined in it, it will be discarded directlyIf there is an object in json that is generated by a constructor, the constructon of the object will be discarded 1.40 Know lodash ? What common APIs does it have?Lodash is a consistent, modular, high-performance JavaScript utility library.
_.cloneDeep Deep copy_.reject Remove an element based on conditions. _.drop(array, [n=1] ) Function: Remove the first n elements in array, and then return the remaining parts. 1.41 LHS and RHS queryLHS (Left-hand Side) and RHS (Right-hand Side) are two ways for the JS engine to operate variables during the code execution phase. The difference between the two is The purpose of variable query is variable assignment or query.
LHS can be understood as the variable is on the left side of the assignment operator (=), for example, a = 1. The purpose of the current engine's search for variable a is variable assignment. In this case, the engine doesn't care what the original value of variable a is, it just assigns the value 1 to variable a. RHS can be understood as the variable is on the right side of the assignment operator (=), for example: console.log(a). The purpose of the engine's search for variable a is to query. It needs to find the actual value corresponding to variable a. What is the value before it can be printed. 1.42 How is includes better than indexOf?includes can detect NaN, indexOf cannot detect NaN, and includes uses Number.isNaN internally to match NaN
1.43 AMD and CMD The difference?
##1.44 (a == 1 && a == 2 && a == 3) Is it possible to be true?
方案一:重写toString()或valueOf() 方案二:数组 数组的toString接口默认调用数组的join方法,重写join方法。定义a为数字,每次比较时就会调用 toString()方法,我们把数组的shift方法覆盖toString即可: 当然把toString改为valueOf也是一样效果: 方案三:使用Object.defineProperty() Object.defineProperty()用于定义对象中的属性,接收三个参数:object对象、对象中的属性,属性描述符。属性描述符中get:访问该属性时自动调用。 1.45 JS中的 MUL 函数 MUL表示数的简单乘法。在这种技术中,将一个值作为参数传递给一个函数,而该函数将返回另一个函数,将第二个值传递给该函数,然后重复继续。例如:xyz可以表示为 1.46 深度遍历广度遍历的区别? 对于算法来说 无非就是时间换空间 空间换时间 1、深度优先不需要记住所有的节点, 所以占用空间小, 而广度优先需要先记录所有的节点占用空间大 2、深度优先有回溯的操作(没有路走了需要回头)所以相对而言时间会长一点 3、深度优先采用的是堆栈的形式, 即先进后出 4、广度优先则采用的是队列的形式, 即先进先出 1.47 JS中的设计模式有哪些? 单例模式 保证一个类仅有一个实例,并提供一个访问它的全局访问点。实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。 策略模式 定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换。 代理模式 为一个对象提供一个代用品或占位符,以便控制对它的访问。 中介者模式 通过一个中介者对象,其他所有的相关对象都通过该中介者对象来通信,而不是相互引用,当其中的一个对象发生改变时,只需要通知中介者对象即可。通过中介者模式可以解除对象与对象之间的紧耦合关系。 装饰者模式 在不改变对象自身的基础上,在程序运行期间给对象动态地添加方法。 1.48 forEach如何跳出循环? forEach是不能通过break或者return来实现跳出循环的,为什么呢?实现过forEach的同学应该都知道,forEach的的回调函数形成了一个作用域,在里面使用return并不会跳出,只会被当做continue 可以利用try catch 1.49 JS中如何将页面重定向到另一个页面? 1、使用 location.href:window.location.href ="url" 2、使用 location.replace: window.location.replace("url"); 1.50 移动端如何实现上拉加载,下拉刷新? 上拉加载 上拉加载的本质是页面触底,或者快要触底时的动作 判断页面触底我们需要先了解一下下面几个属性 scrollTop:滚动视窗的高度距离window顶部的距离,它会随着往上滚动而不断增加,初始值是0,它是一个变化的值 clientHeight:它是一个定值,表示屏幕可视区域的高度; scrollHeight:页面不能滚动时也是存在的,此时scrollHeight等于clientHeight。scrollHeight表示body所有元素的总长度(包括body元素自身的padding) 综上我们得出一个触底公式: 下拉刷新 下拉刷新的本质是页面本身置于顶部时,用户下拉时需要触发的动作 关于下拉刷新的原生实现,主要分成三步: 监听原生touchstart事件,记录其初始位置的值,e.touches[0].pageY; 监听原生touchmove事件,记录并计算当前滑动的位置值与初始位置值的差值,大于0表示向下拉动,并借助CSS3的translateY属性使元素跟随手势向下滑动对应的差值,同时也应设置一个允许滑动的最大值; 监听原生touchend事件,若此时元素滑动达到最大值,则触发callback,同时将translateY重设为0,元素回到初始位置 1.51 JS 中的数组和函数在内存中是如何存储的? Array storage in JavaScript needs to be roughly divided into two situations: Arrays with the same type of data allocate continuous memory space Arrays with non-same type of data use hashing Mapping and allocating memory space Warm reminder: You can imagine that the continuous memory space only needs to directly calculate the storage location based on the index (pointer). If it is a hash map, you first need to calculate the index value, and then if there is a conflict in the index value, you need to perform a second search (you need to know how the hash is stored). 2.1 What is closure? Official statement: Closure refers to a function that has the right to access variables in the scope of another function. MDN statement: Closure is a special object. It consists of two parts: the function, and the environment in which the function is created. The environment consists of any local variables that were in scope when the closure was created. In-depth answer When the browser loads the page, it will put the code in the stack memory (ECStack) for execution. When the function is pushed into the stack, a private context (EC) will be generated. This context can protect the inside. The use of variables (AO) is not subject to external interference, and if some content in the current execution context is occupied by content outside the context, the current context will not be released from the stack, so that the variables and variable values inside can be saved, so I think Closures are a mechanism for saving and protecting internal private variables. 2.2 The role of closure Closure has two common uses; The first of closure The purpose is to enable us to access variables inside the function from outside the function. By using closures, you can access the variables inside the function externally by calling the closure function externally. You can use this method to create private variables. Another use of closure is to allow the variable object in the function context that has ended to remain in memory. Because the closure function retains a reference to the variable object, the variable object will not be recycled. . 2.3 Reference scenarios of closures in projects and the problems they cause In actual projects, closures will be used to Wrap the content of the module you write, so that you can protect your own code as private and prevent conflicts with global variables or other codes. This is to use the protection mechanism. However, it is not recommended to use closures too much, because using a context that is not released takes up stack memory space, and excessive use may lead to memory leaks. The way to solve the memory leak problem caused by closures is to manually release the closure function after using it. 2.4 Usage scenarios of closures return a function Function as parameter IIFE (Self-executing function) Loop assignment Using callback functions is using closures Throttling and anti-shaking Function currying 2.5 Closure execution process Form a private context Push onto the stack to execute a series of operations (1). Initialize the scope chain (both ends (2). Initialize this (3). Initialize arguments (4). Assignment of formal parameters (5). Variable promotion (6). Code execution When encountering a variable, first check whether It is private to you. If it is not private, search it according to the scope chain. If it is not the superior one, continue to search online until EC(G). The search for variables is actually a splicing process of the scope chain, splicing the query chain. The formula is the scope chain. Under normal circumstances, after the code execution is completed, the private context is popped off the stack and recycled. However, in special circumstances, if something in the current private context is occupied by something other than the execution context after the execution is completed, the current private context will not be released from the stack, that is, a context that will not be destroyed is formed, a closure. 2.6 Types of execution context(1) Global execution context Anything that is not inside a function is a global execution Context, it first creates a global window object and sets the value of this equal to this global object. There is only one global execution context in a program. (2) Function execution context When a function is called, a new execution context will be created for the function. There can be any number of function contexts. (3) eval function execution context The code executed in the eval function will have its own execution context, but the eval function is not commonly used and will not be introduced. 2.7 What is the execution context stackThe JavaScript engine uses the execution context stack to manage the execution context When JavaScript executes code, it first encounters global code, creates a global execution context and pushes it into the execution stack. Whenever it encounters a function call, it creates a new execution context for the function and pushes it into the execution stack. On the top of the stack, the engine will execute the function located on the top of the execution context stack. When the function execution is completed, the execution context is popped from the stack and continues to execute the next context. When all code has been executed, the global execution context is popped from the stack. 2.8 Three phases of execution context Creation phase→Execution phase→Recycling phase Creation phase (1) this binding In the global execution context, this points to the global object (window object) In the function execution context, this point depends on how the function is called. If it is called by a reference object, then this will be set to that object, otherwise the value of this is set to the global object or undefined (2) Create a lexical environment component The lexical environment is A data structure with an identifier-variable mapping. The identifier refers to the variable/function name, and the variable is a reference to the actual object or original data. There are two components inside the lexical environment: Bold style: Environment recorder: Used to store the actual location of variables and function declarations External environment reference: Can access the parent scope (3) Create a variable environment component The variable environment is also a lexical environment, and its environment recorder holds the binding relationship created by the variable declaration statement in the execution context. Execution phase In this stage, variable assignment and code execution are performed If the Javascript engine cannot find the value of the variable at the actual location declared in the source code, then it will Assign an undefined value to it Recycling phase Put the execution context off the stack and wait for the virtual machine to recycle the execution context 2.9 Talk about your understanding of scope Scope can be viewed as a set of rules that govern how the engine performs variable lookups based on identifier names in the current scope and nested subscopes. Simply put, scope is the effective range of a variable. Variable data can be read and written in a certain space, and this space is the scope of the variable. (1) Global scope The JS code written directly in the script tag is in the global scope. Variables declared in the global scope are called global variables (variables defined outside the block level). Global variables can be used anywhere in the world; variables in the local scope cannot be accessed in the global scope. The global scope is created when the page is opened and destroyed when the page is closed. All properties of the window object have global scope The global variables and functions declared by the var and function commands are the properties and methods of the window object let command, const command, Global variables declared by the class command do not belong to the attributes of the window object (2) Function scope (local scope) A function scope will be created when a function is called , after the function is executed, the scope is destroyed. Each time a function is called, a new function scope is created, and they are independent of each other. Global variables can be accessed in the function scope, but variables within the function cannot be accessed outside the function. When operating a variable in the function scope, it will first search in its own scope. If there is one, it will be used directly. If not, it will search in the previous scope until it finds the global scope. If the global scope is found, it will be used directly. If it is still not found in the scope, an error will be reported. (3) Block-level scope Before ES6, JavaScript used function scope and lexical scope. ES6 introduced block-level scope. Any statement set in a pair of curly braces {} belongs to a block. Variables declared using let and const in the block cannot be accessed from the outside. This kind of scope rule is called block level. Scope. Variables declared through var or function declarations created in non-strict mode do not have block-level scope. (4) Lexical scope Lexical scope is a static scope. No matter where the function is called or how it is called, its lexical scope Scope is determined only by where the function is declared. The lexical analysis phase of compilation can basically know where all identifiers are and how they are declared, so that it can predict how to find them during execution. In other words, lexical scope means that you have decided the scope of the variable when you write the code. 2.10 What is a scope chain When using a variable in js, first the js engine will try to go down it in the current scope Search for the variable. If not found, search in its upper scope, and so on until the variable is found or has reached the global scope. Such a chain structure of variable scope access is called a scope chain. In-depth answer The scope chain is essentially a list of pointers pointing to variable objects. A variable object is an object that contains all variables and functions in the execution environment. The front end of the scope chain is always the variable object of the current execution context. The variable object of the global execution context (that is, the global object) is always the last object in the scope chain. 2.11 The role of the scope chain The role of the scope chain is to ensure that all variables and functions that have access to the execution environment have access Sequential access, through the scope chain, can access variables and functions in the outer environment. 2.12 Common application scenarios of scope One of the common application scenarios of scope is modularization. Because JavaScript does not natively support modularization, it has led to many mouth-watering problems, such as global scope pollution and variable name conflicts, bloated code structure and low reusability. Before the formal modularization solution was introduced, in order to solve this kind of problem, developers thought of using function scope to create modules. 2.13 Talk about pre-parsing in Js? When the JS engine runs a code, it will work according to the following steps: 1. Promote the declaration of the variable to the front of the current scope , only the declaration will be promoted, but the assignment will not be promoted 2. Promote the function declaration to the front of the current scope, only the statement will be promoted, but the call will not be promoted 3. Promote first function, when promoting var #2.14 What is the difference between variable promotion and function promotion? Variable promotion Simply put, the engine will precompile before the JavaScript code is executed. During the precompilation period, the variable declaration and function declaration will be promoted to their corresponding roles. At the top of the scope, variables declared within a function will only be promoted to the top of the function scope. When a variable defined inside the function is the same as the outside, the variable within the function body will be raised to the top. Function promotion Function promotion will only improve function declarative writing, function expression writing does not exist function promotion The priority of function promotion is greater than the priority of variable promotion , that is, function hoisting is above variable hoisting 2.14 How to extend the scope chain? The scope chain can be extended. Extend the scope chain: There are only two types of execution environments, global and local (function). However, some statements can temporarily add a variable object at the front end of the scope chain, and the variable object will be removed after the code is executed. Specifically, when these two statements are executed, the scope chain will be strengthened try-catch block of the catch statement: a new variable object will be created, containing the thrown out of the declaration of the error object. with statement: The with statement will add the specified object to the scope chain. 2.15 Browser garbage collection mechanism (1) Memory life cycle The memory allocated in the JS environment generally has the following life cycle: Memory allocation: When we declare variables, functions, and objects, the system will automatically allocate memory for them Memory usage: that is Reading and writing memory, that is, using variables, functions, etc. Memory recycling: After use, the memory that is no longer used is automatically recycled by garbage collection Global variables are generally not recycled, and generally local variables are The value, if no longer used, will be automatically recycled (2) The concept of garbage collection Garbage collection: When JavaScript code is running, memory space needs to be allocated for storage Variables and values. When the variables are no longer participating in the operation, the system needs to reclaim the occupied memory space. This is garbage collection. Recycling mechanism: Javascript has an automatic garbage collection mechanism, which will regularly release the memory occupied by variables and objects that are no longer used. The principle is to find variables that are no longer used, and then Release the memory it occupies. There are two types of variables in JavaScript: local variables and global variables. The life cycle of global variables will continue until the page is unloaded; while local variables are declared in a function, and their life cycle starts from the execution of the function until the end of the function execution. During this process, local variables will store their values in the heap or stack. , when the function execution ends, these local variables are no longer used, and the space they occupy will be released. However, when local variables are used by external functions, one of the situations is closure. After the function execution ends, the variables outside the function still point to the local variables inside the function. At this time, the local variables are still being used. Used, so not recycled. (3) Garbage collection method 1. Reference counting method This is relatively rarely used, the reference counting algorithm used by IE. Reference counting keeps track of the number of times each value is referenced. When a variable is declared and a reference type is assigned to the variable, the number of references to the value is 1. Conversely, if the variable containing a reference to this value obtains another value, the number of references to this value is decremented by one. When the number of references becomes 0, it means that the variable has no value. Therefore, the memory space occupied by this variable will be released the next time it is run during the machine recycling period. This method will cause the problem of circular reference: for example: obj1 and obj2 refer to each other through attributes, and the number of references of both objects is 2. When using loop counting, since after the function is executed, both objects leave the scope and the function execution ends, obj1 and obj2 will continue to exist, so their number of references will never be 0, which will cause a circular reference. 2. Mark clearing method Modern browsers no longer use the reference counting algorithm. Most modern browsers use some improved algorithms based on the mark-and-clear algorithm, and the overall ideas are the same. Mark clearing is a common garbage collection method in browsers. When a variable enters the execution environment, it is marked as "entering the environment". Variables marked as "entering the environment" cannot be recycled because they is being used. When a variable leaves the environment, it will be marked as "leaving the environment", and the variable marked as "leaving the environment" will be released from memory. The garbage collector will mark all variables stored in memory when it runs. Then, it removes the variables in the environment and the tags referenced by the variables in the environment. Variables that are marked after this will be regarded as variables to be deleted because variables in the environment can no longer access these variables. at last. The garbage collector completes the memory cleaning work, destroys those marked values, and reclaims the memory space they occupy. (4) How to reduce garbage collection Although the browser can automatically collect garbage, when the code is more complex, the cost of garbage collection is relatively high. , so garbage collection should be minimized. Optimize the array: When clearing an array, the simplest way is to assign it a value of [ ], but at the same time a new empty object will be created, and the length of the array can be set to 0. This is used to achieve the purpose of clearing the array. Optimize objects: Reuse objects as much as possible. For objects that are no longer used, set them to null and recycle them as soon as possible. Optimize functions: If the function expression in the loop can be reused, try to place it outside the function. (5) What is a memory leak refers to the failure of the program to release memory that is no longer used due to negligence or error (6) Which situations will cause memory leaks The following four situations will cause memory leaks: Unexpected global variables: Unexpected due to the use of undeclared variables A global variable is created, leaving this variable in memory and unable to be recycled. Forgotten timer or callback function: Set the setInterval timer and forget to cancel it. If the loop function has a reference to an external variable, then the variable will remain in the memory and cannot be Be recycled. Detached from DOM reference: Get a reference to a DOM element, and then the element is deleted. Since the reference to this element is always retained, it cannot be recycled. Closure: Improper use of closures causes some variables to remain in memory. 3.1 What is functional programming Function Formal programming is a "programming paradigm" (programming paradigm), a methodology for writing programs There are three main programming paradigms: imperative programming, declarative programming and functional programming Compared with imperative programming, functional programming places more emphasis on the results of program execution rather than the execution process. It advocates the use of a number of simple execution units to make the calculation results progressive, and to derive complex operations layer by layer, rather than designing a complex execution process 3.2 Advantages and Disadvantages of Functional Programming Advantages Better management of state: because its purpose is to be stateless , or less states, can minimize these unknowns, optimize code, and reduce error situations Simpler reuse: fixed input->fixed output, no influence from other external variables, and no side effect. In this way, when code is reused, there is no need to consider its internal implementation and external effects. More elegant combination: Broadly speaking, a web page is composed of various components. In smaller terms, a function may also be composed of multiple small functions. Stronger reusability brings more powerful combination hidden benefits. Reduce the amount of code and improve maintainability Disadvantages 性能:函数式编程相对于指令式编程,性能绝对是一个短板,因为它往往会对一个方法进行过度包装,从而产生上下文切换的性能开销 资源占用:在 JS 中为了实现对象状态的不可变,往往会创建新的对象,因此,它对垃圾回收所产生的压力远远超过其他编程方式 递归陷阱:在函数式编程中,为了实现迭代,通常会采用递归操作 3.3 什么是纯函数,它有什么优点 纯函数是对给定的输入返还相同输出的函数,并且要求你所有的数据都是不可变的,即纯函数=无状态+数据不可变 特性: 函数内部传入指定的值,就会返回确定唯一的值 不会造成超出作用域的变化,例如修改全局变量或引用传递的参数 优势: 使用纯函数,我们可以产生可测试的代码 不依赖外部环境计算,不会产生副作用,提高函数的复用性 可读性更强 ,函数不管是否是纯函数 都会有一个语义化的名称,更便于阅读 可以组装成复杂任务的可能性。符合模块化概念及单一职责原则 3.4 什么是组合函数 (compose) 在函数式编程中,有一个很重要的概念就是函数组合,实际上就是把处理的函数数据像管道一样连接起来,然后让数据穿过管道连接起来,得到最终的结果。 组合函数,其实大致思想就是将 多个函数组合成一个函数,c(b(a(a(1)))) 这种写法简写为 compose(c, b, a, a)(x) 。但是注意这里如果一个函数都没有传入,那就是传入的是什么就返回什么,并且函数的执行顺序是和传入的顺序相反的。 组合函数的思想,在很多框架中也被使用,例如:redux,实现效果来说是其实和上面的代码等价。 3.5 什么是惰性函数 惰性载入表示函数执行的分支只会在函数第一次掉用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支了 惰性函数相当于有记忆的功能一样,当它已经判断了一遍的话,第二遍就不会再判断了。 比如现在要求写一个test函数,这个函数返回首次调用时的new Date().getTime(),注意是首次,而且不允许有全局变量的污染 3.6 什么是高阶函数 高阶函数是指使用其他函数作为参数、或者返回一个函数作为结果的函数。 3.7 说说你对函数柯里化的理解 柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。 函数柯里化的好处: (1)参数复用:需要输入多个参数,最终只需输入一个,其余通过 arguments 来获取 (2)提前确认:避免重复去判断某一条件是否符合,不符合则 return 不再继续执行下面的操作 (3)延迟运行:避免重复的去执行程序,等真正需要结果的时候再执行 3.8 什么是箭头函数,有什么特征 使用 "箭头" ( => ) 来定义函数. 箭头函数相当于匿名函数, 并且简化了函数定义 箭头函数的特征: 箭头函数没有this, this指向定义箭头函数所处的外部环境 箭头函数的this永远不会变,call、apply、bind也无法改变 箭头函数只能声明成匿名函数,但可以通过表达式的方式让箭头函数具名 箭头函数没有原型prototype 箭头函数不能当做一个构造函数 因为 this 的指向问题 箭头函数没有 arguments 在箭头函数内部访问这个变量访问的是外部环境的arguments, 可以使用 ...代替 3.9 说说你对递归函数的理解 如果一个函数在内部调用自身本身,这个函数就是递归函数 其核心思想是把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解 一般来说,递归需要有边界条件、递归前进阶段和递归返回阶段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回 优点:结构清晰、可读性强 缺点:效率低、调用栈可能会溢出,其实每一次函数调用会在内存栈中分配空间,而每个进程的栈的容量是有限的,当调用的层次太多时,就会超出栈的容量,从而导致栈溢出。 3.10 什么是尾递归 尾递归,即在函数尾位置调用自身(或是一个尾调用本身的其他函数等等)。 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储,递归次数过多容易造成栈溢出 这时候,我们就可以使用尾递归,即一个函数中所有递归形式的调用都出现在函数的末尾,对于尾递归来说,由于只存在一个调用记录,所以永远不会发生"栈溢出"错误 3.11 函数传参,传递复杂数据类型和简单数据类型有什么区别 传递复杂数据类型传递的是引用的地址,修改会改变 简单数据类型传递的是具体的值,不会相互影响 3.12 函数声明与函数表达式的区别 函数声明: funtion开头,有函数提升 函数表达式: 不是funtion开头,没有函数提升 3.13 什么是函数缓存,如何实现? 概念 函数缓存,就是将函数运算过的结果进行缓存 本质上就是用空间(缓存存储)换时间(计算过程) 常用于缓存数据计算结果和缓存对象 如何实现 实现函数缓存主要依靠闭包、柯里化、高阶函数 应用场景 对于昂贵的函数调用,执行复杂计算的函数 对于具有有限且高度重复输入范围的函数 对于具有重复输入值的递归函数 对于纯函数,即每次使用特定输入调用时返回相同输出的函数 3.14 call、apply、bind三者的异同 共同点 : 都可以改变this指向; 三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefined或null,则默认指向全局window 不同点: call 和 apply 会调用函数, 并且改变函数内部this指向. call 和 apply传递的参数不一样,call传递参数使用逗号隔开,apply使用数组传递,且apply和call是一次性传入参数,而bind可以分为多次传入 bind是返回绑定this之后的函数 应用场景 call 经常做继承. apply经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值 bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指 【相关推荐:JavaScript视频教程、web前端】let a = {
i: 1,
toString: function () {
return a.i++;
}
}
console.log(a == 1 && a == 2 && a == 3); // true
let a = [1,2,3];
a.toString = a.shift;
console.log(a == 1 && a == 2 && a == 3); // true
let a = [1,2,3];
a. valueOf = a.shift;
console.log(a == 1 && a == 2 && a == 3); // true
var _a = 1;
Object.defineProperty(this,'a',{
get:function(){
return _a++
}
})
console.log(a===1 && a===2 && a===3)//true
const mul = x => y => z => x * y * z
console.log(mul(1)(2)(3)) // 6
function getItemById(arr, id) {
var item = null;
try {
arr.forEach(function (curItem, i) {
if (curItem.id == id) {
item = curItem;
throw Error();
}
})
} catch (e) {
}
return item;
}
scrollTop + clientHeight >= scrollHeight
2. Closure and scope
3. Functions and functional programming
var compose = (...funcs) => {
// funcs(数组):记录的是所有的函数
// 这里其实也是利用了柯里化的思想,函数执行,生成一个闭包,预先把一些信息存储,供下级上下文使用
return (x) => {
var len = funcs.length;
// 如果没有函数执行,直接返回结果
if (len === 0) return x;
if (len === 1) funcs[0](x);
return funcs.reduceRight((res, func) => {
return func(res);
}, x);
};
};
var resFn = compose(c, b, a, a);
resFn(1);
//一般会这样实现
var test = (function () {
var t = null;
return function () {
if (t) {
return t;
}
t = new Date().getTime();
return t;
}
})();
// 用惰性函数实现
var test = function () {
var t = new Date().getTime();
test = function () {
return t;
}
return test();
}
console.log(test());
console.log(test());
console.log(test());
/* let a = 8
function fn(a) {
a = 9
}
fn(a)
console.log(a) // 8 */
let a = { age: 8 }
function fn(a) {
a.age = 9
}
fn(a)
console.log(a.age) // 9
The above is the detailed content of JavaScript 10,000 words interview summary. For more information, please follow other related articles on the PHP Chinese website!