美文网首页
javascript basic concept 2023-05

javascript basic concept 2023-05

作者: 9_SooHyun | 来源:发表于2023-12-18 12:40 被阅读0次

    1. javascript运行环境 Node.js

    Node.js or Node is an open-source, cross-platform, JavaScript runtime environment(JSRE) that executes JavaScript code outside of a web browser. Node.js基于 Chrome V8 引擎

    Node.js只是javascript runtime之一,浏览器也是javascript runtime

    Q&A

    • javascript是单线程的,为什么可以执行异步操作?
      如以下异步代码,console.log("Asynchronous")需要10秒后才执行,但它不会block console.log(greet_two);
      setTimeout is asynchronous so it runs in background, allowing code after it to execute while it runs
    let greet_one = "Hello"
    let greet_two = "World!!!"
    console.log(greet_one)
    setTimeout(function(){
        console.log("Asynchronous");
    }, 10000)
    console.log(greet_two);
    

    因为runtime维护了线程池,所有的异步操作都交给了runtime执行

    之所以说JavaScript是单线程,是因为浏览器在运行时只开启了一个JS引擎线程来解析和执行JS。为什么只有一个引擎呢?如果同时有两个线程去操作DOM,涉及线程安全问题,导致渲染页面的复杂度增加

    虽然JavaScript是单线程的,可是浏览器内部不是单线程的。一些I/O操作、定时器的计时和事件监听(click, keydown...)等都是由浏览器提供的其他线程来完成的

    2. 运行环境管理 using nvm

    像go/python一样,Node.js也有很多版本,我们可以通过nvm选择特定版本的Node.js作为运行环境

    nvm: Node Version Manager.
    install nvm: https://github.com/nvm-sh/nvm
    nvm usage:

    nvm install 16.19.1
    $ nvm use 16
    Now using node v16.9.1 (npm v7.21.1)
    $ node -v
    v16.9.1
    

    3. javascript包管理 using NPM

    NPM is a package manager for Node.js packages, which will allow you to install third party libraries (other people's code) by using the command line.

    www.npmjs.com hosts thousands of free packages to download and use. The NPM program is installed on your computer when you install Node.js.

    usage:

    npm install <foo>  # add the <foo> dependency to your project
    

    4. 语法

    变量/常量定义

    变量定义使用let
    常量定义使用const

    > let b = 1
    undefined
    > b = 2
    2
    > 
    > const a = 1
    undefined
    > a = 2
    Uncaught TypeError: Assignment to constant variable.
    > 
    > const obj = {a:1}
    undefined
    > obj.a = 2 // 正常赋值。因为obj是一个引用,记录的是内存地址,引用本身并没有发生变化
    2
    > 
    

    如果你需要一个不变的值,并且确定它的值在声明后不会更改,那么使用 const 可以帮助减少代码中错误赋值的可能性。
    如果需要可变的量,那么使用 let 即可

    注意:对于引用类型的变量,=====只会判断引用的地址是否相同,而不会判断对象具体里属性以及值是否相同

    支持embedding方式创建object

    js支持通过embedding创建object,类似golang中使用struct-embedding创建新struct一样(https://gobyexample.com/struct-embedding)

    如果你不需要给object的属性再起名字,可以直接通过embedding创建object

    > let name = "john"
    undefined
    > let age = 10
    undefined
    > let doHomeWork = () => { return "doing homework" }
    undefined
    > let student1 = {name, age, doHomeWork} // create obj by embedding other objs
    undefined
    > student1
    { name: 'john', age: 10, doHomeWork: [Function: doHomeWork] }
    > 
    

    js is Prototype-based

    js is a Prototype-based language. Prototype-based programming is a style of object-oriented programming in which classes are not explicitly defined, but rather derived by adding properties and methods to an instance of another class or, less frequently, adding them to an empty object.

    In simple words: this type of style allows the creation of an object without first defining its class.

    // Example of true prototypal inheritance style 
    // in JavaScript.
    
    // object creation using the literal 
    // object notation {}.
    const foo = { name: "foo", one: 1, two: 2 };
    
    // Another object.
    const bar = { two: "two", three: 3 };
    
    // Object.setPrototypeOf() is a method introduced in ECMAScript 2015.
    // For the sake of simplicity, let us pretend 
    // that the following line works regardless of the 
    // engine used:
    Object.setPrototypeOf(bar, foo); // foo is now the prototype of bar.
    
    // If we try to access foo's properties from bar 
    // from now on, we'll succeed. 
    bar.one; // Resolves to 1.
    
    // The child object's properties are also accessible.
    bar.three; // Resolves to 3.
    
    // Own properties shadow prototype properties
    bar.two; // Resolves to "two"
    bar.name; // unaffected, resolves to "foo"
    foo.name; // Resolves to "foo"
    

    For another example:

    const foo = { one: 1, two: 2 };
    
    // bar.[[prototype]] = foo
    const bar = Object.create(foo);
    
    bar.three = 3;
    
    bar; // { three: 3 }
    bar.one; // 1
    bar.two; // 2
    bar.three; // 3
    

    原型

    JavaScript 中所有的对象都有一个内置属性,称为它的 prototype(原型)。它本身是一个对象,故原型对象也会有它自己的原型,逐渐构成了原型链。原型链终止于拥有 null 作为其原型的对象上。

    有个对象叫 Object.prototype,它是最基础的原型,所有对象默认都拥有它。Object.prototype 的原型是 null,所以它位于原型链的终点

    设置原型

    使用 Object.create
    const personPrototype = {
      greet() {
        console.log("hello!");
      },
    };
    
    const carl = Object.create(personPrototype); // create改叫createFrom更贴切
    carl.greet(); // hello!
    
    使用构造函数

    如果我们设置一个构造函数的 prototype,我们可以确保所有用该构造函数创建的对象都被赋予该原型:

    const personPrototype = {
      greet() {
        console.log(`你好,我的名字是 ${this.name}!`); // `this`就是调用方
      },
    };
    
    // 构造函数Person
    function Person(name) {
      this.name = name;
      this.sing = function() {
        console.log(`${this.name} singing!`); // `this`就是调用方
      }
    }
    
    Object.assign(Person.prototype, personPrototype);
    const carl = new Person('carl');
    carl.greet();  // 你好,我的名字是 carl!
    // new 在执行时会做四件事情:
    
    //   ① 在内存中创建一个新的空对象。
    
    //   ② 让 this 指向这个新的对象。
    
    //   ③ 执行构造函数里面的代码,给这个新对象添加属性和方法。
    
    //   ④ 返回这个新对象(所以构造函数里面不需要 return )
    
    
    const bob = new Person('bob');
    console.log(bob.greet === carl.greet); //  True. 因为都是引用prototype.greet -> 构造函数通过原型分配的函数是所有对象所共享的
    console.log(bob.sing === carl.sing); //  false. 自有的sing各自持有而不是引用同一份method,其实挺浪费内存空间的
    

    Named Export and Default Export

    Default Export (export default)

    You can have one default export per file. When you import you have to specify a name and import like so:

    import MyDefaultExport from "./MyFileWithADefaultExport";
    

    You can give this any name you like.

    Named Export (export)

    With named exports, you can have multiple named exports per file. Then import the specific exports you want surrounded in braces:

    // ex. importing multiple exports:
    import { MyClass, MyOtherClass } from "./MyClass";
    // ex. giving a named import a different name by using "as":
    import { MyClass2 as MyClass2Alias } from "./MyClass2";
    
    // use MyClass, MyOtherClass, and MyClass2Alias here
    

    Or it's possible to use a default along with named imports in the same statement:

    import MyDefaultExport, { MyClass, MyOtherClass} from "./MyClass";
    

    js语言特性

    数据类型体系

    • 基本数据类型。基本数据类型对象直接分配在栈中,如数字、字符串,然后持有引用

      JavaScript 中的基本数据类型(例如字符串、数字、布尔值等)是不可变的。这意味着当你重新为一个变量赋值时,实际上是在内存中创建了一个新的值,并将变量引用这个新值。原始值在内存中的位置不会改变,但变量引用的内存地址将指向新值。

      let s = 'hello'
      s = 'world'
      

      在这个例子中,我们首先将变量 s 赋值为字符串 'hello'。当我们将 s 重新赋值为 'world' 时,实际上是创建了一个新的字符串 'world',并将变量 s 指向这个新字符串。原始字符串 'hello' 仍然存在于内存中,但变量 s 现在引用的是新字符串 'world' 的内存地址。

    • 容器类型。容器类型的对象分配在堆中,然后在栈中持有堆对象的引用

    动态语言,变量xxx的类型可以随便改,如xxx = 1然后xxx = [1,2,3],这个特性决定了动态语言都要依赖引用(实际上是对指针的再封装)。如果像golang把xxx固定为一个int长度的内存空间,那xxx就无法再被赋值为数组了。对任何数据类型重新赋值,都是修改了引用;而对引用的容器类型对象进行局部修改,不改变引用本身,整体和Python的类型机制相同。可见动态语言出于其动态特性,类型系统都是一个套路

    因此,js的const,it does not define a constant value. It defines a constant reference to a value instance.

    值传递

    在 JavaScript 中,所有参数都是按值传递的。但是对于对象(包括数组和函数),传递的值本身是对象的引用,引用作为值,因此它们的行为看起来像是按引用传递。这样的话,如果你在函数内部修改了一个对象参数的属性,那么在函数外部,这个属性的原始对象也会被修改。

    JavaScript 有 5 种基本的数据类型,分别是:bool、null、undefined、string 和 number,还有另外三种引用类型: Array、Function 和 Object。此外,在 ES6 中,引入了一种新的数据类型 - Symbol - 是一种原始数据类型,像数字或字符串一样按值进行传递。

    总结一下,基本类型(Number、String、Boolean、Undefined、Null、Symbol)由于空间小、数据简单,Javascript按值传递(复制一份到新的栈),引用类型(Object)由于空间大、数据复杂,Javascript按共享传递(复制引用到新的栈)。

    相关文章

      网友评论

          本文标题:javascript basic concept 2023-05

          本文链接:https://www.haomeiwen.com/subject/ctfdsdtx.html