Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What if the median value of JavaScript is undefined?

2025-02-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)05/31 Report--

This article introduces the relevant knowledge of "how to deal with JavaScript median undefined". In the operation of actual cases, many people will encounter such a dilemma. Next, let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

In JavaScript, when you want to get the value of a variable or object (uninitialized), the js engine returns undefined.

Let company; company; / / = > undefined let person = {name: 'John Smith'}; person.age; / / = > undefined

Object reference errors, on the other hand, return null. JavaScript itself does not set the value of a variable or object property to null.

Some js native methods return null, such as null when the string.prototypt.match () parameter is not an object, indicating that the object is missing.

Let array = null; array; / / = > null let movie = {name: 'Starship Troopers', musicBy: null}; movie.musicBy; / / = > null' abc'.match (/ [0-9] /); / / = > null

Because of JavaScript's tolerant nature, developers have the temptation to access uninitialized values. I also committed this bad practice.

Usually this kind of risk-taking will result in "undefined" related errors, which can quickly end the script. Related common error messages are:

TypeError:'undefined' is not a function

TypeError: unable to read undefined properties'

And similar to type errors.

JavaScript developers can understand this joke:

Function undefined () {/ / problem solved}

To reduce the risk of this error, you must understand what happens when "undefined" is generated.

More importantly, it suppresses its appearance and spreads in the application, thus improving the durability of the code.

Let's explore undefined and its impact on code security in detail.

1. What is undefined

6 basic types of JavaScript:

Boolean: true or false

Number: 1, 6.7, 0xFF

String: "Gorilla and banana"

Symbol: Symbol ("name") (starting ES2015)

Null: null

Undefined: undefined.

And a separated object type: {name: "Dmitri"}, ["apple", "orange"].

From the 6 basic types undefined is a special value, and its type is Undefined. According to [ECMAScript Specification] (https://www.ecma-international.org/ecma-262/7.0/#sec-undefined-value):

The original value of the undefined value is used when the variable is not assigned.

The standard makes it clear that you will receive undefined values when accessing uninitialized variables, non-existent object attributes, nonexistent array elements, and so on.

For example: Try in repl.it

Let number; number; / / = > undefined let movie = {name: 'Interstellar'}; movie.year; / / = > undefined let movies = [' Interstellar', 'Alexander']; movies [3]; / / = > undefined

The ECMAScript specification defines the type of "undefined" value:

An undefined type is the only type whose value is an undefined value.

Typeof undefined = = 'undefined'; / / = > truelet nothing; typeof nothing = =' undefined'; / / = > true2, create common undefined scenes

2.1 uninitialized variables

A declared variable (uninitialized) that has not been assigned defaults to undefined.

Plain and simple:

Let myvariable; myvariable; / / = > undefined

An effective way to solve the problem of uninitialized variables is to assign an initial value _ as much as possible.

The fewer variables exist in an uninitialized state, the better. Ideally, you can assign a value immediately after the value const myvariable = 'initial value' is declared, but this is not always possible.

Tip 1: approve of const, otherwise use let, but say goodbye to var

In my opinion, one of the excellent features of ECMAScript 2015 is the new way to declare variables using const and let. This is a big step forward, as these declarations are block-scoped (as opposed to the old function scope var) and exist in the [temporary dead zone] (https://rainsoft.io/variables-lifecycle-and-why-let- is not suspended / # 5letvariableslifecycle) until the declaration line.

When a variable receives only one value, I recommend using the const declaration.

It creates an immutable binding (https://mathiasbynens.be/notes/es6-const).

A good feature of const is that you have to assign the variable const myvariable = 'initial' to the initial value. Variables are not exposed to uninitialized state, and it is simply impossible to access undefined.

Let's check to see if the word is a function that verifies palindromes:

Function isPalindrome (word) {const length = word.length; const half = Math.floor (length / 2); for (let index = 0; index `

< half; index++) { if (word[index] !== word[length - index - 1]) { return false; } } return true; } isPalindrome('madam'); // =>

`true isPalindrome ('hello'); / / = > false

The problem declared by var is the function-wide [variable promotion] (https://rainsoft.io/javascript-hoisting-in-details/#hoistingandvar)).

You can declare a var variable at the end of the function scope, but it can still be accessed before the declaration: and you will get a undefined.

Function bigFunction () {/ / code... Myvariable; / / = > undefined / / code... Var myVariable = 'Initial value'; / / code... MyVariable; / / = > 'Initial value'} bigFunction ()

In contrast, the let (including const) variable cannot be accessed before the row is declared. This occurs because the variable is in the temporary dead zone (https://rainsoft.io/variables-lifecycle-and-why-let-is-not-hoisted/#5letvariableslifecycle)) before it is declared.

This is good because you have fewer opportunities to visit undefined.

When the above example is rewritten in let, it will make an error.

Function bigFunction () {/ / code... MyVariable; / / = > Throws' ReferenceError: myVariable is not defined' / / code... Let myVariable = 'Initial value'; / / code... MyVariable; / / = > 'Initial value'} bigFunction ()

Tip 2: enhance cohesion

[Cohesion] (https://en.wikipedia.org/wiki/Cohesion_(computer_science)) describes the extent to which elements of modules (namespaces, classes, methods, code blocks) belong. The measurement of cohesion is usually described as high cohesion or low cohesion.

High cohesion is best because it recommends that the elements of the design module focus only on a single task. It makes the module:

Focused and understandable: easier to understand what the module does

Single function and easy to understand

Maintainable and easier to refactor: the change in the module affects fewer modules

Easy to maintain and reuse

Reusable: being focusing on a single task, it makes the module easier to reuse

reuse

Testable: you would easier test a module that's focused on a single task

Easy to test

High cohesion is accompanied by [loose coupling] (https://en.wikipedia.org/wiki/Loose_coupling) is a feature of a well-designed system.

A code block itself may be thought of as a small module. To benefit from the benefits of high cohesion, you need to keep variables as close as possible to the blocks of code that use them.

For example, if a variable exists entirely in the logic that forms the scope of the block, declare and allow the variable to exist only within that block (using const or let declaration). Do not expose this variable to the external block scope, because the external block should not care about this variable.

A typical example of an unnecessary extension variable life cycle is the use of a for loop within a function:

Function someFunc (array) {var index, item, length = array.length; / / some code... / / some code... For (index = 0; index)

< length; index++) { item = array[index]; // some code... } return 'some result'; } index,item和length变量在函数体的开头声明。然而,它们只用于接近尾声。那么这种方法有什么问题? 在顶部的声明和for语句中的用法之间,变量index,item都是未初始化的并且暴露给undefined。它们在整个功能范围内的生命周期不合理。 更好的方法是将这些变量尽可能靠近他们的使用地点: function someFunc(array) { // some code... // some code... const length = array.length; for (let index = 0; index `< length; index++) { const item = array[index]; // some } return 'some result'; } 为什么修改后的版本比最初版本更好?让我们来看看: 变量不会暴露于未初始化的状态,因此您没有访问未定义的风险 尽可能将变量移动到它们的使用地点增加了代码的可读性 高度连贯的代码块在需要时更容易重构并提取为分离的函数 2.2 访问不存在的属性 When accessing a **non-existing object property**, JavaScript returnsundefined`. 当访问不再的属性时,会返回undefined 看例子: let favoriteMovie = { title: 'Blade Runner' }; favoriteMovie.actors; // =>

Undefined

Accessing properties that do not exist by itself does not raise an error. A real problem occurs when trying to get data from a property value that never exists. This is the most common undefined-related trap, reflected in the well-known error message 'TypeError:Can not read property

Let's modify the previous code snippet slightly to illustrate a "TypeError" throw:

Let favoriteMovie = {title: 'Blade Runner'}; favoriteMovie.actors [0]; / / TypeError: Cannot read property' 0' of undefined

The tolerant nature of JavaScript that allows access to a property that does not exist is a source of confusion: the property may or may not be set. The ideal way to get around this problem is to restrict an object from always defining the properties it has.

Unfortunately, you often have no control over the objects you use. These objects may have different property sets in different situations. So you have to deal with all these scenarios manually.

Let's implement a function append (array,toAppend) that adds new elements to the beginning and / or end of the array. The toAppend parameter accepts an object with attributes:

First: element inserted at the beginning of array

Last: element inserted at the end of array.

Function append (array, toAppend) {const arrayCopy = array.slice (); if (toAppend.first) {arrayCopy.unshift (toAppend.first);} if (toAppend.last) {arrayCopy.push (toAppend.last);} return arrayCopy;} append ([2,3,4], {first: 1, last: 5}); / / > [1,2,3,4,5] append (['Hello'], {last:' World'}) / / = > [Hello', 'World'] append ([8,16], {first: 4}); / / = > [4,8,16] append ([10], {first: 0, last: false}); / / = > [10]

The following tips explain how to correctly check for the existence of properties.

Tip 3: check whether the property exists

Fortunately, JavaScript provides a number of ways to determine whether an object has specific properties:

* obj. Propellants = undefined: compare directly with undefined

Typeof obj. Propelled attribute values undefined: verify the type of property value * obj.hasOwnProperty ('prop'): verify that the object has its own properties

The 'prop': in obj` verifies that the object has its own or inherited properties

My suggestion is to use the in operator. It has a short and sweet grammar. The existence of the in operator means that the explicit purpose is to check whether the object has a specific property without accessing the actual property value.

! [do not write var, write const and place it in JavaScript] (https://p0.ssl.qhimg.com/t010effea86a232d8a4.png)

Obj.hasOwnProperty ('prop') is also a good solution. It is slightly longer than the in operator and is validated only in the object's own properties.

Two ways to compare with 'undefined'' may work. But it seems to me that obj. Propellant processes = undefined and typeof obj. Propellant examples' undefined 'look lengthy and bizarre and expose the suspected path of dealing with undefined directly.

Let's use the in operator to improve the append (array,toAppend) function:

Function append (array, toAppend) {const arrayCopy = array.slice (); if ('first' in toAppend) {arrayCopy.unshift (toAppend.first);} if (' last' in toAppend) {arrayCopy.push (toAppend.last);} return arrayCopy;} append ([2,3,4], {first: 1, last: 5}); / / > [1,2,3,4,5] append ([10], {first: 0, last: false}) / / = > [0,10, false]

Tip 4: access the properties of an object in a structured way

When accessing an object property, it is sometimes necessary to indicate the default value if the property does not exist.

You can use in with the ternary operator to do this:

Const object = {}; const prop = 'prop' in object? Object.prop: 'default'; prop; / / = >' default'

When the number of attributes to check increases, the use of ternary operator syntax becomes difficult. For each property, you must create a new line of code to handle the default values, adding an ugly wall of ternary operators similar to the appearance.

To use a more elegant approach, let's familiarize ourselves with a great ES2015 feature called object destructuring. [object deconstruction] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring) allows you to extract the value of an object property directly into a variable and set the default value if this property does not exist.

A simple syntax to avoid dealing with undefined directly.

In fact, the current property parsing looks short and clear:

Const object = {}; const {prop = 'default'} = object; prop; / / = >' default'

To see the actual situation, let's define a useful function that wraps the string in quotation marks. Quote (subject,config) accepts the first parameter as the string to wrap. The second parameter, config, is an object with the following properties:

Char: quote characters, such as (single quotation marks) or (double quotation marks), default to `. SkipIfQuoted: skips the referenced Boolean value if the string is already referenced. The default is true.

To apply the benefits of object deconstruction, let's implement the use of backquotes:

Function quote (str, config) {const {char ='", skipIfQuoted = true} = config; const length = str.length; if (skipIfQuoted & & str [0] = char & & str [length-1] = char) {return str;} return char + str + char;} quote ('Hello World', {char:' *'}); / / >'* Hello World*' quote ('" Welcome "', {skipIfQuoted: true}) / / = > 'Welcome "````const {char ='', skipIfQuoted = true} = config` deconstruct assignment extract attributes `char` and `skipIfQuoted` from `config` object on one line. If some attributes are not available in `config` object, set the default value to: 'char','false' is' skipIfQuoted`. Fortunately, there is room for improvement. Let's move the deconstruction assignment to the parameters section. Set a default value for the `config` parameter (an empty object `{}`) to skip the second parameter when the default setting is sufficient. [Try in repl.it] (https://repl.it/HK1b/0) ```javascript function quote (str, {char ='", skipIfQuoted = true} = {}) {const length = str.length; if (skipIfQuoted & & str [0] = char & & str [length-1] = char) {return str;} return char + str + char;} quote ('Hello World', {char:' *'}) / / = >'* Hello World*' quote ('Sunny day'); / / >' Sunny day'

Note that deconstructing the assignment replaces the "config" parameter in the function signature. I like it this way: quote () becomes a shorter line. The = {} to the right of the deconstructing assignment ensures that the empty object is used when the second parameter is not specified in quote ('Sunny day') `.

Object deconstruction is a powerful feature that can effectively deal with the extraction of attributes from objects. I like the possibility of specifying the default value to return when the accessed property does not exist. As a result, "undefined" and the problems associated with dealing with it are avoided.

Tip 5: populate objects with default properties

If you do not need to create variables for each attribute as you deconstruct the allocation, objects that lack some attributes can be populated with default values.

ES2015Object.assign (target,source1,source2,...) Copies the values of all enumerable properties from one or more source objects to the target object. This function returns the target object.

For example, you need to access a property of a unsafeOptions object, which does not always contain all of its properties.

To avoid undefined when accessing an attribute that doesn't exist in unsafeOptions, let's make some adjustments:

Define an object defaults that holds the default attribute value

Call Object.assign ({}, defaults,unsafeOptions) to build a new object options. The new object receives all properties from unsafeOptions, but the missing attributes are from defaults.

Const unsafeOptions = {fontSize: 18}; const defaults = {fontSize: 16, color: 'black'}; const options = Object.assign ({}, defaults, unsafeOptions); options.fontSize; / / = > 18 options.color; / / = >' black'

Object.assign () takes the first parameter as the target object {}. The target object receives the value of the fontSize property from the unloaded options source object. And the value from the color property of the defaults source object, because unsafeOptions does not contain color. The order in which the source objects are enumerated is important: later source object properties will overwrite the previous object properties.

You can now securely access any property of the options object, including options.color, which was initially not available in unsafeOptions.

Fortunately, it is easier to populate objects with default properties. I suggest a new JavaScript feature (now in [stage 3] (https://tc39.github.io/process-document/)), which allows [to propagate properties in object initializers] (https://github.com/ TC39/ proposes objects, the rest of the extensions).

Instead of the Object.assign () call, use the object extension syntax to copy all properties and enumerable attributes from the source object to the target object:

Const unsafeOptions = {fontSize: 18}; const defaults = {fontSize: 16, color: 'black'}; const options = {... defaults,... unsafeOptions}; options.fontSize; / / = > 18 options.color; / / = >' black'

Object initializers propagate properties from defaults and unloaded options source objects. It is important to specify the order of the source objects: later source object properties overwrite the previous object properties.

Populating incomplete objects with default property values is an effective strategy to make your code secure and stable. Regardless of the situation, the object always contains all the properties: 'undefined' cannot be generated.

2.3 parameters of the function

The function parameter defaults to undefined.

In general, functions defined with a specific number of parameters should be called with the same number of arguments. In this case, these parameters will get the values you expect:

Function multiply (a, b) {a; / / = > 5 b; / / = > 3 return a * b;} multiply (5, 3); / / = > 15

What happens when you omit parameters in the call? The arguments inside the function become undefined.

Let's modify the previous example slightly to call the function with only one argument:

Function multiply (a, b) {a; / / = > 5 b; / / = > undefined return a * b;} multiply (5); / / = > NaN

Tip 6: give default values to parameters

Sometimes a function does not need a full set of parameters to call. You can simply set default values for parameters that have no value.

Look at the example:

Function multiply (a, b) {if (b = undefined) {b = 2;} a; / / = > 5 b; / / = > 2 return a * b;} multiply (5); / / = > 10

The function is invoked with a single argument multiply (5). Initially a parameter is 2 and b is undefined. The conditional statement verifies whether b is undefined. If it happens, b = 2 assignment sets a default value.

Although a way to assign default values is provided, I do not recommend comparing 'undefined' directly. It's lengthy and looks like a hacker.

A better approach is to use ES2015 [default parameters] (https://www.sitepoint.com/es6-default-parameters/) feature). It is short, expressive, and has no direct contrast with 'undefined'.

Example modification to add default values:

Function multiply (a, b = 2) {a; / = > 5 b; / / = > 2 return a * b;} multiply (5); / / = > 10 multiply (5, undefined); / / = > 10

The default parameter feature of ES2015 is very intuitive and efficient. Always use it to set default values for optional parameters.

2.4 function return value

Implicitly, without a return statement, the JavaScript function returns undefined.

In JavaScript, functions without any return statements implicitly return undefined:

Function square (x) {const res = x * x;} square (2); / / = > undefined

The square () function does not return any calculation results. The result of the function call is' undefined'.

The same thing happens when the return statement exists, but there is no expression nearby:

Function square (x) {const res = x * x; return;} square (2); / / = > undefined

The return; statement is executed, but it does not return any expressions. The result of the call is also undefined.

Of course, near 'return', the expression to be returned works as expected:

Function square (x) {const res = x * x; return res;} square (2); / / > 4

Tip 7: don't trust automatic semicolon insertion

The following JavaScript statement list must end with a semicolon (;):

An empty statement

Let,const,var,import,export statement

Expression statement

Debugger statement

Continue statement, break statement

Throw out a declaration

Return statement

If you use one of the above sentences, be sure to specify the semicolon at the end:

Function getNum () {/ / Notice the semicolons at the end let num = 1; return num;} getNum (); / / = > 1

A mandatory semicolon is written at the end of the let statement and the return declaration.

What happens when you don't want to add these semicolons? For example, reduce the size of the source file.

In this case, ECMAScript provides [Automatic Semicolon Insertion] (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-automatic-semicolon-insertion)(ASI) mechanism, which can insert your missing semicolon.

With the help of ASI, you can remove the semicolon from the previous example:

Function getNum () {/ / Notice that semicolons are missing let num = 1 return num} getNum () / / = > 1

The above text is a valid JavaScript code. Missing semicolons are automatically inserted.

At first glance, it looks promising. The ASI mechanism allows you to skip unnecessary semicolons. You can make the JavaScript code smaller and easier to read.

ASI has a small and annoying trap. When a newline character is between return and the returned expression 'return\ nexpression, ASI automatically inserts a semicolon before the newline character;\ nthe expression.

What return; statement does it mean inside the function? This function returns undefined. If you do not understand the mechanism of ASI in detail, the unexpected return of "undefined" is misleading.

For example, let's look at the return value of the getPrimeNumbers () call:

Function getPrimeNumbers () {return [2,3,5,7,11,13,17]} getPrimeNumbers () / / = > undefined

There is a new line between the return statement and the array literal expression. JavaScript automatically inserts a semicolon after return. The interpretation code is as follows:

Function getPrimeNumbers () {return; [2, 3, 5, 7, 11, 13, 17];} getPrimeNumbers (); / / = > undefined

The statement return; causes the getPrimeNumbers () function to return undefined instead of the expected array.

You can solve the problem by removing the newline character between return and array literal:

Function getPrimeNumbers () {return [2,3,5,7,11,13,17];} getPrimeNumbers (); / / = > [2,3,5,7,11,13,17]

My suggestion is to study the role of http://www.bradoncode.com/blog/2015/08/26/javascript-semi-colon-insertion/) automatic semicolon insertion to avoid this situation.

Of course, never put a newline between return and the returned expression.

2.5 void operation

Void operation, evaluates an expression, does not return the result, so the return value is undefined

Void 1; / / = > undefined void (false); / / = > undefined void {name: 'John Smith'}; / / = > undefined void Math.min (1,3); / / = > undefined

[a use case] of the [void use] operator (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void#JavaScript_URIs) suppresses expression evaluation to undefined, relying on some side effects of evaluation.

3. Undefined in the array

You get when accessing an array element with an out of bounds index. Undefined is returned when you try to get a subscript that is outside the bounds of the array

Const colors = ['blue',' white', 'red']; colors [5]; / / = > undefined colors [- 1]; / / = > undefined

The array colors has three elements, array has 3 elements, corresponding to 0 and 1 and 2, respectively. Because there is no subscript 5 and-1 in the array, undefined is returned when you t visit colors [5] and colors [- 1].

You may encounter so-called sparse arrays in JavaScript. These are arrays with gaps, that is, no elements are defined in some indexes.

When you access a gap (also known as an empty slot) in a sparse array, you also get an 'undefined'.

The following example generates a sparse array and attempts to access its empty slot:

Const sparse1 = new Array (3); sparse1; / / = > [``,``, ``] sparse1 [0]; / / = > undefined sparse1 [1]; / / = > undefined const sparse2 = ['white',' blue'] sparse2; / / = > ['white',``,' blue'] sparse2 [1]; / / = > undefined

Sparse1 is created by calling the constructor "Array" constructor. It has three empty slots. Sparse2 creates an array with empty second elements in literal form. In any of these sparse arrays, the result of accessing an empty slot is "undefined".

To avoid capturing undefined when working with arrays, be sure to use valid array indexes and avoid creating sparse arrays.

4. The difference between undefined and null

Here's a reasonable question: undefined and null, what are the main differences between them? Is a specified value used to represent an empty state.

The main difference is that undefined is used to indicate that the value of a variable is not defined. Null this represents an object that does not exist.

Let's take a look at these differences:

When the variable number is defined, but no value is assigned to it for initialization:

Let number; number; / / = > undefined

So the value of the variable number is undefined,. This clearly indicates that it is an uninitialized variable.

Similarly, this happens when you get a property that exists in an object: the property is not initialized.

Const obj = {firstName: 'Dmitri'}; obj.lastName; / / = > undefined

In the above example, because obj has no lastName attribute, JavaScript parses obj.lastName to undefined.

There is another case when a variable expects an object or a method returns an object, but for some reason, you cannot instantiate an object. In such a case, null would be a meaningful indicator to indicate that the object is missing.

For example: clone () `is a function that copies a JavaScript object, and this function expects to return an object.

Function clone (obj) {if (typeof obj = = 'object' & & obj! = = null) {return Object.assign ({}, obj);} return null;} clone ({name:' John'}); / / = > {name: 'John'} clone (15); / / > null clone (null); / / = > null

Then, you may pass in a parameter that is not an object: 15 _ null. In this case, the function cannot copy the object, so it returns null-- to indicate that the object is missing

The typeof operation can see the difference between two values.

Typeof undefined; / / = > 'undefined' typeof null; / / = >' object'

The The congruence operator = = also shows inequality for undefined and null.

Let nothing = undefined; let missingObject = null; nothing = missingObject; / / = > false "how to deal with undefined in JavaScript" is introduced here. Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report