10 JavaScript difficulties that you may not know yet, don’t worry, this article lists them one by one and overcomes them one by one. Interested friends can refer to
to understand this blog JavaScript developers will not have bad luck...
1. Immediately execute the function
Immediately execute the function, that is, Immediately Invoked Function Expression (IIFE), as it is The name means that the function is executed immediately when it is created. It does not bind any events and does not need to wait for any asynchronous operations:
(function() { // 代码 // ... })();
function(){…} is an anonymous function, and a pair of parentheses surrounding it convert it into an expression, followed by A pair of parentheses calls this function. Executing a function immediately can also be understood as calling an anonymous function immediately. The most common application scenario of executing a function immediately is to limit the scope of the var variable to your function, so as to avoid naming conflicts.
2. Closure
For closure, when the external function returns, the internal function can still access the variables of the external function.
function f1() { var N = 0; // N是f1函数的局部变量 function f2() // f2是f1函数的内部函数,是闭包 { N += 1; // 内部函数f2中使用了外部函数f1中的变量N console.log(N); } return f2; } var result = f1(); result(); // 输出1 result(); // 输出2 result(); // 输出3
In the code, the external function f1 is executed only once, the variable N is set to 0, and the internal function f2 is assigned to the variable result. Since the external function f1 has been executed, its internal variable N should be cleared in the memory. However, this is not the case: every time we call result, we find that the variable N has been in the memory and is accumulating. why? This is the magic of closures!
3. Use closures to define private variables
Usually, JavaScript developers use underscores as prefixes for private variables. But in fact, these variables can still be accessed and modified, and are not truly private variables. At this time, you can use closures to define real private variables:
function Product() { var name; this.setName = function(value) { name = value; }; this.getName = function() { return name; }; } var p = new Product(); p.setName("Fundebug"); console.log(p.name); // 输出undefined console.log(p.getName()); // 输出Fundebug
In the code, the name attribute of object p is a private attribute and cannot be accessed directly using p.name.
4. prototype
Each JavaScript constructor has a prototype attribute, which is used to set the properties and methods that all instance objects need to share. The prototype property cannot be enumerated. JavaScript only supports inheritance of properties and methods through the prototype attribute.
function Rectangle(x, y) { this._length = x; this._breadth = y; } Rectangle.prototype.getDimensions = function() { return { length: this._length, breadth: this._breadth }; }; var x = new Rectangle(3, 4); var y = new Rectangle(4, 3); console.log(x.getDimensions()); // { length: 3, breadth: 4 } console.log(y.getDimensions()); // { length: 4, breadth: 3 }
In the code, x and y are both object instances created by the constructor Rectangle, and they inherit the getDimensions method through prototype.
5. Modularity
JavaScript is not a modular programming language, at least not until ES6 is implemented. However, for a complex Web application, modular programming is the most basic requirement. At this time, you can use immediate execution functions to achieve modularity, just as many JS libraries such as jQuery and our Fundebug are implemented this way.
var module = (function() { var N = 5; function print(x) { console.log("The result is: " + x); } function add(a) { var x = a + N; print(x); } return { description: "This is description", add: add }; })(); console.log(module.description); // 输出"this is description" module.add(5); // 输出“The result is: 10”
The so-called modularization is to control the accessibility of attributes and methods in the module according to needs, that is, private or public. In the code, module is an independent module, N is its private property, print is its private method, description is its public property, and add is its public method.
6. Variable Hoisting
JavaScript will move all variable and function declarations to the front of its scope. This is called variable hoisting (Hoisting). That is, no matter where you declare variables and functions, the interpreter will move them to the front of the scope. So we can use variables and functions first and then declare them.
However, only the variable declaration is promoted, but the variable assignment will not be promoted. If you don't understand this, sometimes an error will occur:
console.log(y); // 输出undefined y = 2; // 初始化y
The above code is equivalent to the following code:
var y; // 声明y console.log(y); // 输出undefined y = 2; // 初始化y
To avoid bugs, developers should start each scope with Declare variables and functions.
7. Currying
Currying, that is, Currying, can make functions more flexible. We can call it by passing in multiple parameters at once; we can also call it by passing in only part of the parameters and let it return a function to process the remaining parameters.
var add = function(x) { return function(y) { return x + y; }; }; console.log(add(1)(1)); // 输出2 var add1 = add(1); console.log(add1(1)); // 输出2 var add10 = add(10); console.log(add10(1)); // 输出11
In the code, we can pass in two 1's as parameters to add(1)(1) at one time, or we can pass in one parameter and then get the add1 and add10 functions, which is very flexible to use.
8. apply, call and bind methods
JavaScript developers need to understand the differences between apply, call and bind methods. What they have in common is that the first parameter is this, which is the context that the function depends on when running.
Among the three, the call method is the simplest. It is equivalent to calling a function by specifying this value:
var user = { name: "Rahul Mhatre", whatIsYourName: function() { console.log(this.name); } }; user.whatIsYourName(); // 输出"Rahul Mhatre", var user2 = { name: "Neha Sampat" }; user.whatIsYourName.call(user2); // 输出"Neha Sampat"
The apply method is similar to the call method. The only difference between the two is that the apply method uses an array to specify parameters, while the call method requires each parameter to be specified individually:
apply(thisArg, [argsArray]) call(thisArg, arg1, arg2, …) var user = { greet: "Hello!", greetUser: function(userName) { console.log(this.greet + " " + userName); } }; var greet1 = { greet: "Hola" }; user.greetUser.call(greet1, "Rahul"); // 输出"Hola Rahul" user.greetUser.apply(greet1, ["Rahul"]); // 输出"Hola Rahul"
Using the bind method, you can bind this value to the function and then use it as a new function Return:
var user = { greet: "Hello!", greetUser: function(userName) { console.log(this.greet + " " + userName); } }; var greetHola = user.greetUser.bind({greet: "Hola"}); var greetBonjour = user.greetUser.bind({greet: "Bonjour"}); greetHola("Rahul") // 输出"Hola Rahul" greetBonjour("Rahul") // 输出"Bonjour Rahul"
9. Memoization
Memoization is used to optimize time-consuming calculations by caching the calculation results into memory, so that for the same input value, Next time you only need to read the results from memory.
function memoizeFunction(func) { var cache = {}; return function() { var key = arguments[0]; if (cache[key]) { return cache[key]; } else { var val = func.apply(this, arguments); cache[key] = val; return val; } }; } var fibonacci = memoizeFunction(function(n) { return (n === 0 || n === 1) ? n : fibonacci(n - 1) + fibonacci(n - 2); }); console.log(fibonacci(100)); // 输出354224848179262000000 console.log(fibonacci(100)); // 输出354224848179262000000
In the code, the second calculation of fibonacci(100) only needs to read the result directly from the memory.
10. Function overloading
所谓函数重载(method overloading),就是函数名称一样,但是输入输出不一样。或者说,允许某个函数有各种不同输入,根据不同的输入,返回不同的结果。凭直觉,函数重载可以通过if…else或者switch实现,这就不去管它了。jQuery之父John Resig提出了一个非常巧(bian)妙(tai)的方法,利用了闭包。
从效果上来说,people对象的find方法允许3种不同的输入: 0个参数时,返回所有人名;1个参数时,根据firstName查找人名并返回;2个参数时,根据完整的名称查找人名并返回。
难点在于,people.find只能绑定一个函数,那它为何可以处理3种不同的输入呢?它不可能同时绑定3个函数find0,find1与find2啊!这里的关键在于old属性。
由addMethod函数的调用顺序可知,people.find最终绑定的是find2函数。然而,在绑定find2时,old为find1;同理,绑定find1时,old为find0。3个函数find0,find1与find2就这样通过闭包链接起来了。
根据addMethod的逻辑,当f.length与arguments.length不匹配时,就会去调用old,直到匹配为止。
function addMethod(object, name, f) { var old = object[name]; object[name] = function() { // f.length为函数定义时的参数个数 // arguments.length为函数调用时的参数个数 if (f.length === arguments.length) { return f.apply(this, arguments); } else if (typeof old === "function") { return old.apply(this, arguments); } }; } // 不传参数时,返回所有name function find0() { return this.names; } // 传一个参数时,返回firstName匹配的name function find1(firstName) { var result = []; for (var i = 0; i < this.names.length; i++) { if (this.names[i].indexOf(firstName) === 0) { result.push(this.names[i]); } } return result; } // 传两个参数时,返回firstName和lastName都匹配的name function find2(firstName, lastName) { var result = []; for (var i = 0; i < this.names.length; i++) { if (this.names[i] === (firstName + " " + lastName)) { result.push(this.names[i]); } } return result; } var people = { names: ["Dean Edwards", "Alex Russell", "Dean Tom"] }; addMethod(people, "find", find0); addMethod(people, "find", find1); addMethod(people, "find", find2); console.log(people.find()); // 输出["Dean Edwards", "Alex Russell", "Dean Tom"] console.log(people.find("Dean")); // 输出["Dean Edwards", "Dean Tom"] console.log(people.find("Dean", "Edwards")); // 输出["Dean Edwards"]
The above is the detailed content of 10 difficult points that must be mastered in JavaScript (must read). For more information, please follow other related articles on the PHP Chinese website!

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft

SublimeText3 Linux new version
SublimeText3 Linux latest version

Notepad++7.3.1
Easy-to-use and free code editor

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function

Zend Studio 13.0.1
Powerful PHP integrated development environment
