
My more or less serious way of programming began with writing programs in C #, sometimes I tried writing in JavaScript, and every now and then I fell into a stupor in such situations when I incorrectly indicated the name of a variable and found out about it later many many years debugging hour, since there was no my compiler next to me, who would help me out in a difficult moment. After a while, besides C #, I started writing a lot of JavaScript code and now I can do it without much difficulty, I am no longer confused by the implicit type conversion and dynamic typing.
In this article I would like to systematize my basic knowledge of these languages and consider their similarities and differences. This article can serve as a guide for C # developers who want to learn JavaScript and vice versa. I also want to note that this article describes the capabilities of client JS, since I have no development experience on Node.js. So, if you still have not lost interest - let's start.
Namespace and js modules
In each program, in order to avoid conflicts in the names of variables, functions, classes or other objects, we combine them into certain areas. Thus, if two different areas contain elements with the same name, no conflict will occur.
C # uses namespaces to split a program into parts. To declare them, use the namespace
keyword. For example, if we want to create a set of user interface components, then it is logical to put them all in one namespace, for example, Components
. Thus it is accepted that the namespace has the following naming [AssemblyName].[DirectoryName].[DirectoryName].[...]
. In each file, the user interface component class must be placed inside the namespace:
Contents of the ComboBox.cs
file:
namespace AssemblyName.Components { public class ComboBox {
To start using components, you need to import them from the namespace as follows using AssemblyName.Components
. With this connection method in one line, we import all objects into the current file.
In JS, ES modules are used for the same purpose. When using them, we to some extent emulate the behavior of namespaces by writing additional code. Consider the same example with the component library. Suppose we have a Components
folder that contains the components of the user interface ComboBox.js
, Button.js
, Button.js
and so on. In order to get similar behavior compared to the namespace in the Components
folder, you need to create an index.js
file, which will contain the following code:
export { default as Dialog } from './ComboBox'; export { default as Button } from './Button'; export { default as Checkbox } from './Checkbox';
In order to use these components, you must import them into the current file. This can be done as follows: import * as Components from './../Components'
, after the keyword from
we need to specify the path to the folder in which all the described components are located.
Variable declaration methods
var
keyword
As you know, C # is a strongly typed programming language, so when declaring a variable to the compiler, its type must be known; for this, it is usually indicated before its name.
double pi = 3.14; User user = new User(); int[] a = new[] { 0, 1, 2 };
But we can also tell the compiler that it must deduce the type itself from the expression after the assignment sign. This is made possible by the introduction of the keyword var
in version C # 3.0.
With var
we can create objects of anonymous type:
In JavaScript, you can also use the var
keyword to declare variables, however, unlike C #, the scope of these variables will be the entire function or the window
object if the variable was declared outside the function.
var a = 5
Although you have the ability to declare variables using var
in JavaScript, but now it is not recommended to do this, after the release of the ES6 standard, the let
keyword was added, which also allows you to declare variables, but its advantage is that their scope will be the block in which they are declared, not the whole function.
Constants
In both C # and JavaScript, the keyword const
used to declare a constant field. True, it is worth noting that the concept of a constant in this case is different for these languages.
In C #, a constant is an expression that can be fully computed at compile time, i.e. constants can be numbers, logical values, strings or null references ..
const int c1 = 5; const int c2 = c1 + 100; const string c3 = ""; const bool c4 = true; const User human = null; const User human = new User(firstName);
In JavaScript, the value of a constant can also not be changed, but there are no restrictions imposed on the value as in C #, it can be assigned any values / objects / arrays. However, if an object is assigned to a constant, then the constant itself is protected against the change, but not the properties inside it:
const c1 = 5; const c2 = c1 + 100; const c3 = ""; const c4 = true; const user = { name: "" }; user.name = "";
void
keyword
While writing this article, I experimented with functions on the console and, as a result, I started describing a function as in C # void SomeFunction...
, and for me it was a big surprise when I found out that there is a void
keyword in JavaScript. As it turned out, void
in JavaScript is a unary operator that calculates the value of the operand, then discards it and returns undefined
.
alert("!"); // "!" alert(void "!"); // undefined
Thus, we can say that the use of void
clearly indicates the absence of a return value, for more details on examples of its use, you can find in the next article .
In C #, void
not an operator, but in fact it has a similar meaning. Here it indicates the absence of the return value of the function:
public void SampleMethod() {
However, as can be seen in the example above, void
in the place where the type of the return value is usually indicated, and this is not accidental, because in C # void
also a type.
var t = typeof(void); t.Name
void
as a type can only be used in an unsafe context when working with pointers.
unsafe { void* identifier;
Keyword new
In JavaScript, the new
keyword is an operator, and is used in a way that is familiar to many C-like languages — to create an object.
function Animal() { //... } const animal = new Animal();
In C #, new
can be used for the following purposes:
- to create objects;
- to hide the inherited member of the base class;
- to restrict the types that can be used as arguments to the type parameter in the generic class.
The first case is similar to the use of new
in JavaScript.
class Animal {
Basic data types
In each language there are data types - primitives, on the basis of which other data types are built, let's consider the data types provided to us in C # and JavaScript.
C # primitive types:
- Integer with the sign:
sbyte
, short
, int
, long
- Unsigned integer:
byte
, ushort
, uint
, ulong
- Unicode characters:
char
- Unicode character set:
char
- Floating point numbers:
float
, double
- Decimal with increased accuracy:
decimal
- Boolean value:
bool
The base class is Object
.
For JS:
Primitive data types:
- Number
- String
string
- Boolean
boolean
type - Special
null
value - Special value
undefined
symbol
The base type is Object
.
After studying the primitives of both languages, you can come to the following conclusions:
- Instead of a sufficiently large set of numeric types, JavaScript has a single type,
number
; - There is no
char
type in JavaScript, you should use the string
type instead; - In both languages, the base type is
Object
; - A distinctive feature of JS is that
null
and undefined
are separated into separate types, while in C # null
is a keyword meaning no value. - In JS, the
symbol
type is present, which is used primarily within the JavaScript standard itself, in order to be able to add new functionality without conflict with the existing code base.
As a rule, now there are more and more applications in which it is necessary to perform data processing on the client, which requires greater accuracy in calculations. Currently, there is no built-in ability to work with large numbers in JavaScript, however in the near future we plan to add a new type of BigInt
. To solve similar problems in C # there is a class System.Numerics.BigInteger
.
Object Type Check
Type checking is a typical operation enough for most programming languages. Based on the type, we can perform various actions. For example, consider an example from life: you hear a doorbell, if a drunken neighbor came to you (an object with the Drunken Neighbor type) to borrow money, then you are unlikely to open the door for him, but if the door is your best friend (an object with the best friend ), then you do not hesitate to let him into the apartment. C # and JavaScript also provide tools for checking the type of objects.
typeof
operator
For type information, both C # and JavaScript have a typeof
operator. Let's look at how it works in both languages:
In C #, the typeof
operator is applied to a type and returns an object of class Type
, which contains all the information about the type.
namespace Zoo { public class Animal {} } Type t = typeof(Animal); t.Name
In JS, typeof
returns a string indicating the type of the operand.
typeof 30 // 'number' typeof Symbol() // 'symbol' typeof undefined // 'undefined' // typeof new Animal() // object typeof null // 'object' typeof [1,2,3] // 'object' // typeof function() {} // 'function'; typeof class C {} // 'function';
In the example above, you can notice some features of this operator. It seems logical if the expression typeof new Animal()
would return the string 'Animal'
, a typeof [1,2,3]
- the string Array
, but no matter how paradoxical it is, the result in both cases is 'object'
. Also, due to the fact that classes in JS are a wrapper over functions, the expression typeof class C {}
returns 'function'
instead of 'class'
. Another interesting fact is that the typeof null
expression returns an 'object'
. In JavaScript, this operator has a big drawback: all non-primitive objects for it are the same person, they all have the same type object
.
It is worth noting that in JavaScript typeof
you can apply to anything: objects, functions, classes, etc ... In C #, this operator applies only to types.
In addition to obtaining information about the type, it is sometimes useful to check that the object belongs to a particular type.
In C # for these purposes there is an operator is
.
class Person { }
In JavaScript, in order to find out what type the object belongs to, it is necessary to use the - instanceof
operator.
function Person() {} function Programmer() {} // Programmer Person Programmer.prototype = Object.create(Person.prototype); var person = new Person(); var programmer = new Programmer(); console.log(person instanceof Person); // true console.log(person instanceof Programmer); // false console.log(programmer instanceof Person); // true console.log(programmer instanceof Programmer); // true
Boolean and null check
Almost everywhere, in order not to get a Null reference exception
, before using a variable, we check it for null
, and in the case of JavaScript, also for undefined
.
In C #, we constantly see similar code:
if(user != null && String.IsNullOrEmpty(user.name)) { user.SetName(""); }
In JavaScript, this construct can be written slightly shorter. This is due to the fact that, unlike C #, in JavaScript, a set of values other than false
when casting is also regarded as false
:
null
undefined
- "" (empty line)
0
NaN
(not a number)
Thus, the above C # code can be written as follows:
if (user && !user.name) { user.setName(""); }
or
user && !user.name && user.setName("");
Due to the fact that checks for null
occur everywhere, Null Propagation Operator was added to C # 6.0 .?
.
C # code:
if (user != null && user.parent != null && user.parent.parent != null) { user.parent.parent.SetName(""); }
With it, this code section can be rewritten as follows:
user?.parent?.parent?.SetName("");
JavaScript usually does this:
user && user.parent && user.parent.parent && user.parent.parent.setName("");
Setting Default Values
Another common operation is setting default values, from version 2.0 in C # the Null Coalescing Operator appeared - ??
.
The following two lines of C # code are equivalent:
var name = user != null && user.name != null ? user.name : ""; var name = user?.name ?? "";
In JavaScript, this operation is usually done as follows.
var name = user && user.name || "";
However, we can use the operators &&
and ||
only if 0
, false
and the empty string are not valid values.
In the foreseeable future, operators ?.
??
should appear in JavaScript (they have now passed the Stage0 stage), for more information on these operators in JavaScript, see the article .
Keyword this
Both C # and JavaScript have the keyword this
. Usually, in C #, understanding this
purpose is easy, but in JavaScript it is one of the most complex language concepts. Next, consider the use of this
in the examples.
In C #, the keyword this
points to the current instance of the class.
class User { public string Name { get; set; } public void PrintEmployee() { Console.WriteLine(this.name); } } var employee = new Employee(); E1.PrintEmployee();
In this example, in the Console.WriteLine(this.name)
expression Console.WriteLine(this.name)
, this
points to the employee
variable.
Since this
is the current instance of the class, it cannot be used in methods not bound to a specific type, for example, in static methods.
In JavaScript, the value of this
is called the context of the call and will be determined at the time of the function call. If the same function is run in the context of different objects, it will receive a different this
:
var user = { firstName: "" }; var admin = { firstName: "" }; function func() { alert( this.firstName ); } user.f = func; admin.g = func; // this : user.f();
In addition, JavaScript has the ability to explicitly specify the value of this
using functions: call
, bind
, apply
. For example, the above example can be rewritten as follows:
var user = { firstName: "" }; var admin = { firstName: "" }; function func() { alert( this.firstName ); } // this : func.call(user); // func.call(admin); // func.bind(user)();// func.bind(admin)();//
Destructuring
It is often necessary to assign several object fields to local variables. For example, how often do you see such a code?
void Method(User user) { var firstName = user.FirstName; var lastName = user.LastName;
For such purposes, you can use destructuring. This feature is supported to varying degrees by both languages.
In C # 7.0, a new kind of function called deconstructors appeared to support destructuring. In order to declare a deconstructor, we need to define a method called Deconstruct
, all of whose parameters must be declared with an out
modifier:
class Person { public string FirstName { get; set; } public string LastName { get; set; }
Support for destructuring or (destructuring assignment) in JavaScript appeared in the sixth standard EcmaScript. With her help. You can assign an array or an object to several variables at once, breaking it apart.
let [firstName, lastName] = ["", ""]; let [firstName, _ ] = ["", ""]; let { firstName, lastName } = { firstName: "", lastName: "" }; let { firstName } = { firstName: "", lastName: "" };
It should be noted that JavaScript restructuring has more features than in C #:
- Change the order of variables;
- No need to explicitly declare deconstructors;
- Support for array restructuring;
- Setting default values;
- Assigning object properties to a variable with a different name;
- Support nested restructuring.
Conclusion
In this article, we discussed only the most basic concepts of C # and JavaScript. But many aspects remained unaffected:
- collections
- functions
- classes
- multithreading
Each of these topics is quite extensive and will be disclosed further in a separate article.