• 前端(三):JavaScript基础


    JavaScript是一种属于网络的脚本语言,常用来为网页添加各式各样的动态功能,是一种动态类型、弱类型、基于原型的语言。
    它包括三个部分:ECMAScriptBOMDOMECMAScript描述了该语言的语法和基本对象。BOM,浏览器对象模型,描述了与浏览器进行交互的方法和接口。DOM,文档对象模型,描述了处理网页内容的方法和接口。
    js的使用:js代码写在script标签中,其引入方式和css样式的style标签一致。

    一、变量、数据类型与运算符

      1.变量

      声明变量

    - 通过var关键字声明一个或多个变量。
      - 声明变量的同时可以给其赋值(直接量,字面量),也可以不赋值,不赋值时默认值为undefined
      - 变量命名遵循一般的命名规范:区分大小写,不能包含特殊字符,大小驼峰命名或下划线命名,不能以数字开头,命名含义明确等。
      - 变量在内存中会自动存储于释放。

      2.数据类型

    js中的数据类型包括:字符串(String)、数字(Number)、布尔(Boolean)、数组(Array)、对象(Object)、空(Null)、未定义(Undefined)。

      隐式转换

    // 转换为布尔类型
    var a; // undefined.
    var test = function(vec){
    if(vec){
    console.log("true");
    }else{
    console.log("false");
    }
    };
    a = null;
    a = 0; // 0
    a = NaN; // NaN
    a = ''; // 空字符串
    test(a);
    // 转换成数值型数据
    var a;// undefined -> NaN
    var b = 1;
    a = null; // null -> 0
    a = false; // false -> 0
    a = "123"; // "12" -> 12
    a = "123abc"; // "123abc" -> NaN
    console.log(typeof a);
    console.log(b + a);

      强制转换

    // parseInt(string):将字符串类型转换成数值;
    // parseFloat(string):将字符串类型转换成浮点型数值;
    var a = "123";
    console.log(typeof parseInt(a));
    console.log(typeof parseFloat(a));
    // String()toString():将其它类型转换成字符串
    var a = 123;
    console.log(typeof String(a));
    console.log(typeof a.toString());
    // Boolean:将其它数据类型转换成布尔值。;
    var a = undefined;
    console.log(Boolean(a), typeof Boolean(a));

      3.运算符

      1.算术运算符

    +-*/%++--
    ++--分为前缀形式和后缀形式。前缀先自加()再执行运算,后缀先执行运算再自加()

      2.赋值运算符和比较运算符

    =+=-=*=/=%=.=
    >>=<<===!====!==

      3.逻辑运算符

    &&||!

      4.三元运算符

    // exp1?exp2:exp3
    var a = 1231; // var a;
    typeof a==="number"?console.log("true"):console.log("false");

      5.运算符优先级

    运算符 描述
    . [] () 字段访问、数组下标、函数调用以及表达式分组
    ++ -- - ~ ! delete new typeof void 一元运算符、返回数据类型、对象创建、未定义值
    * / % 乘法、除法、取模
    + - + 加法、减法、字符串连接
    << >> >>> 移位
    < <= > >= instanceof 小于、小于等于、大于、大于等于、instanceof
    == != === !== 等于、不等于、严格相等、非严格相等
    & 按位与
    ^ 按位异或
    | 按位或
    && 逻辑与
    || 逻辑或
    ?: 条件
    = oP= 赋值、运算赋值
    , 多重求值

    二、流程控制

      1.条件语句

    // if(exp){执行代码段};
    var a = 123; // var a;
    if(typeof a === "number"){
    console.log("true");
    }
    // if(exp){exptrue的代码段}else{expfalse的代码段};
    var a = 123; // var a;
    if(typeof a === "number"){
    console.log("true");
    }else {
    console.log("false");
    }
    // if ... else if ...
    var readline = require("readline");
    var rl = readline.createInterface({
    input: process.stdin,
    out: process.stdout,
    });
    rl.question("请输入成绩: ", (number) => {
    if(number > 100){
    console.log("输入的成绩不能大于100");
    }else if(number > 80){
    console.log("录入成功,A");
    }else if(number > 60){
    console.log("录入成功,B");
    }else if(number > 0){
    console.log("录入成功,C");
    }else{
    console.log("输入的成绩不能小于0")
    }
    rl.close();
    });
    rl.on("close", function () {
    console.log("退出程序!");
    process.exit();
    });
    var readline = require("readline");
    var rl = readline.createInterface({
        input: process.stdin,
        out: process.stdout,
    });
    rl.question("请输入星期几: ", (day) => {
        switch(day){
            case "1":
                console.log("今天吃炒面");
                break;
            case "2":
                console.log("今天吃鱼香肉丝");
                break;
            case "3":
                console.log("今天吃麻辣香锅盖饭");
                break;
            case "4":
                console.log("今天吃豆丁胡萝卜");
                break;
            case "5":
                console.log("今天公司聚餐");
                break;
            case "6":
                console.log("今天吃泡面");
                break;
            case "7":
                console.log("今天撸串");
                break;
            default:
                console.log("input error.")
        }
    
        rl.close();
    });
    rl.on("close", function () {
        process.exit();
    }
    // switch ... case ...
    var readline = require("readline");
    var rl = readline.createInterface({
    input: process.stdin,
    out: process.stdout,
    });
    rl.question("请输入星期几: ", (day) => {
    switch(day){
    case "1":
    console.log("今天吃炒面");
    break;
    case "2":
    console.log("今天吃鱼香肉丝");
    break;
    case "3":
    console.log("今天吃麻辣香锅盖饭");
    break;
    case "4":
    console.log("今天吃豆丁胡萝卜");
    break;
    case "5":
    console.log("今天公司聚餐");
    break;
    case "6":
    console.log("今天吃泡面");
    break;
    case "7":
    console.log("今天撸串");
    break;
    default:
    console.log("input error.")
    }

    rl.close();
    });
    rl.on("close", function () {
    process.exit();
    });

      2.循环语句

      for 循环

    java中的for循环一致:for(exp1; exp2; exp3){代码块;}
      - exp1: 无条件的执行第一个表达式
      - exp2: 是判断是否能执行循环体的条件
      - exp3: 增量操作

    // 九九乘法表
    var str = "";
    for(var i=1;i<=9;i++){
    for(var j=1;j<=i;j++){
    str += i + "*" + j + "=" + i*j + " ";
    if(i === j){
    str += " ";
    }
    }
    }
    console.log(str);

      while 循环

    var arr = function (number) {
        var arr_list = new Array(); // var arr_list = [];
        var i = 0;
        while (i < number){
            arr_list[i] = Math.random();
            i++;
        }
        return arr_list;
    };
    console.log(arr(5))
    var arr = function (number) {
    var arr_list = new Array(); // var arr_list = [];
    var i = 0;
    while (i < number){
    arr_list[i] = Math.random();
    i++;
    }
    return arr_list;
    };
    console.log(arr(5));

      do ... while循环

    
    
    // java中的do ... while 循环一致,先执行依次do内的代码块,再执行while 判断。不管while条件判断是否成功,do都会至少执行一次。
    var arr = function (number) {
    var arr_list = new Array(); // var arr_list = [];
    var i = 0;
    do {
    arr_list[i] = Math.random();
    i++;
    }while (i > number);
    return arr_list;
    };
    console.log(arr(5));

    三、函数

      1.定义

      函数通过function关键字定义。function 函数名称([参数1, ...]){代码块; [return 返回值]};也可以通过Function构造器定义函数。

    
    
    // 通过function 关键字定义函数
    function hello() {
    console.log("hello world.")
    };
    hello();

      匿名函数,即function关键字定义的无函数名称的函数。

    // 通过function 关键字定义匿名函数
    var hello = function () {
    console.log("hello world.")
    };
    hello();

      将匿名函数作为参数,传递给另一个函数进行执行,此时其被称为回调函数。回调函数在js中异常强大。

    function calc(v1, v2, callback) {
    v1 = v1 || 1;
    v2 = v2 || 2;
    return callback(v1, v2);
    }
    calc(3,4, function (v1, v2) {
    return v1 + v2
    });

      

      2.参数

      函数如果定义了参数,在调用函数的时候没有传值则默认值为undefined。如果传递的参数超过了形参,js会忽略掉多于的参数值。

    function  calc(v1, v2){
    return v1 + v2;
    }
    console.log(calc(5, 6, 7));

      es5不能直接写形参的默认值,但可以通过arguments对象来实现默认值。同时,arguments对象可以实现可变参数。

    function  calc(v1, v2){
    v1 = v1 || 1;
    v2 = v2 || 2;
    return v1 + v2;
    }
    console.log(calc());

      3.函数调用

    function calc(v1, v2, callback) {
    v1 = v1 || 1;
    v2 = v2 || 2;
    return callback(v1, v2);
    }
    value1 = calc(3,4, function (v1, v2) {
    return v1 + v2
    });

    value2 = calc.call(calc, 3, 4, function (v1, v2) {
    return v1 + v2;
    });

    value3 = calc.apply(calc, [3, 4, function (v1, v2) {
    return v1 + v2;
    }]);

    value4 = (function (v1, v2) {
    return v1 + v2;
    })(3, 4);
    console.group("函数调用的方式");
    console.log("- 直接调用: " + value1);
    console.log("- 间接call调用: " + value2);
    console.log("- 间接apply调用: " + value3);
    console.log("- 自调用: " + value4);

    四、对象

      js中对象分为:内建对象、宿主对象和自定义对象。

      1.对象创建

      直接通过var关键字定义Object对象。

    var obj1 = new Object();
    var obj2 = {};
    // 使用字面量来创建一个对象: var obj = {} new本质上是一模一样的
    // 使用字面量创建对象时,可以在创建对象时直接指定对象中的属性
    // 字面量里面的属性可以加引号,也可以不加引号,建议不加
    // 如果使用特殊字符或名字则必须加引号
    var obj = {
    name: "孙悟空",
    gender: "男猴",
    age: 1500,
    credit: {
    name1: "孙行者",
    name2: "齐天大圣"
    }
    };
    console.log(obj);

      也可以通过工厂方法创建对象。

    function Person(name, age) {
    var obj = {};
    obj.name = name;
    obj.age = age;
    obj.sayHello = function () {
    console.log(obj.name + ", " + obj.age + "years old.");
    };
    return obj;
    }
    sun = Person("孙悟空", 2000);
    sun.sayHello();

      2.对象属性操作和方法创建

    
    
    var obj = new Object(); // new 构造对象, 可使用typeof obj 查看对象
    // 在对象中保存的值称为属性
    // 向对象中添加属性:对象.属性名 = 属性值
    obj.name = "孙悟空";
    obj.gender = "男猴";
    obj.age = 18;
    console.log(obj);
    // 读取对象中的属性: 对象.属性名
    // 如果读取的对象中没有该属性,会返回undefined
    console.log(obj.name);
    // 修改对象的属性值: 对象.属性名 = 新值
    obj.age = 24;
    console.log(obj);
    // 删除对象属性
    delete obj.age;
    console.log(obj);
    // 自定义
    obj.fuc = function add(x, y) {
    return x+y;
    };
    console.log(obj);
    
    

      3.作用域

    js中一共有两种作用域,全局作用域和函数作用域
    全局作用域:
    - 直接编写在script标签内的JS代码
    - 在页面打开时创建,在页面关闭时销毁
    - 在全局作用域中有一个全局对象window,可以直接使用.它代表的是一个浏览器的窗口,它由浏览器创建
    - 在全局作用域中创建的变量都会作为window对象的属性保存
    - 在全局作用域中创建的函数都会作为window对象的方法保存
    - 全局作用中的变量和函数在页面的任意位置都可以被访问/执行

      函数作用域:
      - 调用函数时创建函数作用域,函数执行完毕之后,函数作用域销毁
      - 每调用一次函数就会创建一个新的函数作用域,它们之间是相互独立的
      - 全局作用域中访问不到函数作用域,函数作用域中可以访问全局作用域
       - 函数作用域会优先查找本作用域中的变量,如果没有就找上一级中的变量
      - 函数作用域的a并不影响上一级作用域中的a
    - 如果不使用var声明,直接写a = 20,就是在操作全局作用域中的a变量
    - 如果使用全局作用域中的a变量[在本作用域中已声明a变量],可以用window.a,这在b1中已强调过

      全局作用域

    console.log(window); // window是个对象

    // 使用var关键字声明的变量,会在所有的代码执行之前执行;如果声明变量时不使用var,则变量不会被提前声明
    console.log(a); // 此时的var a已被声明,它的值是undefined,到下一行时它的值才会是123

    var a = 123; // 它相当于window.a = 123
    console.log(window.a);

    console.log(abc()); // 可以提前声明和执行
    console.log(abc2()); // var提前声明的是一个undefinedwindow属性,不是个函数: abc2 is not a function

    // 使用function关键字声明的函数,和var的机制一样,是函数声明的提前,它会提前(优先)执行
    function abc() { // 它相当于window.abc = function (){console.log("abc")}
    console.log("abc");
    }
    console.log(window.abc());

    // 使用函数表达式不会被声明提前
    var abc2 = function() {
    console.log("abc2");
    }

      局部作用域

    var a = 19;
    var b = 30;
    function fun() {
    a = 20;
    var b = 1000;
    console.log("a = " + a); // 这里打印的是20
    console.log("b = " + b); // 这里打印的是1000
    console.log("window.b = " + window.b); // 这里打印的是30
    }
    fun();
    console.log(a); // 这里打印的是20
    // 定义形参相当于在函数作用域中声明了变量

    五、原型

      1.this关键字

    解析器在调用函数时,会向函数内部传递进一个隐含的参数这个隐含的参数就是thisthis指向的是一个对象,这个对象称为函数执行的上下文对象
    根据函数的调用方式不同,this会指向不同的对象
    - 1.以函数的形式调用时,this永远都是window
    - 2.以方法的形式调用时,this就是调用方法的那个对象
    var name = "全局名字";
    function func(a, b) {
    console.log("a = " + a + ", b = " + b);
    console.log(" Object: " + this);
    console.log(this);
    }
    func(123, 456); // this指的是window
    function func2() {
    console.log(this.name);
    console.log(this);
    }
    var obj = {
    name: "孙悟空",
    sayName: func, // 把函数赋给属性,this指的是obj
    sayName2: func2

    };
    var obj2 = {
    name: "猪八戒",
    sayName: func, // this指的是obj2
    sayName2: func2
    };
    obj2.sayName(2332, 4523);
    obj.sayName(234, 789);
    obj.sayName2(); // this可以支持对象内部的函数去访问对象内部的属性
    obj2.sayName2(); // 这一点特别像python类中的self
    
    
    var obj3 = {
    name: "沙和尚",
    teacher: "唐僧",
    address: "流沙河",
    sayMyTeacher: function3,
    sayMySelf: function2,
    say: function1
    };
    function function1() {
    var say = this.sayMySelf() + this.sayMyTeacher();
    console.log(say);
    }
    function function2() {
    var say = "大家好,我是" + this.name + ",我老家是" + this.address;
    return say
    }
    function function3() {
    var say = "。我的师父是" + this.teacher + "老师, 他是个得道高僧";
    return say
    }
    obj3.say();

      2.构造方法的重写

    
    
    function Person1(name, age, gender) {
    this.name = name;
    this.age = age;
    this.gender = gender;
    // this.sayName = function() {
    // console.log("大家好,我系" + this.name); // 这样写每创建一个对象,就会创建一个sayName
    // }
    this.sayName = sayName; // 共用同一个方法,它就相当于python中的类方法[类方法只有一份,但每个实例对象都共用]
    } // 注意这里的写法,一个隐含的this传递给了sayName函数
    var per1 = new Person1("孙悟空", 18, "");
    per1.sayName();

    // 在全局作用域中写sayName
    // 但是它污染了全局作用域的命名空间,也就是全局作用域不能再写sayName函数
    // 另外这个函数也很不安全,由此引出了"原型"的概念
    function sayName() {
    console.log("大家好,我系" + this.name);
    }

      3.原型

      1.原型prototype


    我们所创建的每一个函数,解析器都会向函数中添加一个属性:prototype
    如果函数作为普通函数调用prototype,没有任何作用
    当该函数以构造函数的形式调用[per1]时,它[per1]会有一个隐含的属性__proto__指向其原型对象[Person]
    每次调用时都会有各自的__proto__指向原型对象的prototype也就是原型对象中的属性和方法被调用函数"共享"
    function Person() {}
    console.log(Person.prototype);

    var per1 = new Person();
    console.log(per1.__proto__ == Person.prototype); // true

    Person.prototype.a = "我是原型对象中的123456";
    per1.a = "我是mc中的" +"123456";

    var per2 = new Person();
    console.log(per1.a); // 找到调用函数的属性和方法,直接执行
    console.log(per2.a); // 如果调用函数没有该属性或方法,会从原型对象中寻找

    Person.prototype.sayName = function() {
    console.log('我是原型对象的sayName');
    };
    per2.sayName = function() {
    console.log('我是per2中的sayName');
    };
    per1.sayName(); // 和前面的类似
    per2.sayName(); // 和前面的类似
    // 解决全局作用域污染问题: 把对象的函数写在prototype里而不是全局作用域里
    function MyPerson(name, age, gender) {
    this.name = name;
    this.age = age;
    this.gender = gender;
    }
    MyPerson.prototype.sayName = function() {
    console.log("大家好,我系" + this.name);
    };
    var mp1 = new MyPerson("孙悟空", 2000, "男猴");
    mp1.sayName();

      2.原型模拟类和对象

      在python中声明一个类和对象:

    class Person(object):
      def __init__(self, name, age):
        self.name = name
        self.age = age
      def sayHello(self):
        print("{}, {} years old.".format(self.name, self.age))

    sun = Person("孙悟空", 2000)
    sun.sayHello() // 对象可以调用方法,因为方法只有一份且存在类内存中,每个对象只保留了引用
    Person.sayHello(sun) // 类可以传入一个对象来调用方法,因为方法存在类内存中

      在Java中创建一个类和对象:类的方法存在方法区,对象存在堆内存中,多个对象共用它们父类的方法。它需要设置静态方法来实现对象调用。

    public class Person {
    private String name;
    private int age;
    Person(String name, int age){
      this.name = name;
      this.age = age;
      }  
      public void sayHello(){
      System.out.println(this.name + ", " + this.age + "years old.");
      }
      public static void sayHello(Person obj){
      System.out.println(obj.name + ", " + obj.age + "years old.");
      }
      public static void main(String[] args){
      Person sun = new Person("孙悟空", 2000);
      Person.sayHello(sun);
      sun.sayHello();
      }
    }

      在js中,对象保存在堆内存中,每创建一个新的对象都会开一个堆内存空间,并把其属性和方法都保存在堆内存中。注意,如果不用原型,每个对象都会将其方法复制一份到自己的堆内存空间中。js中实现类调用实例对象:

    function MyPerson(name, age, gender) {
    this.name = name;
    this.age = age;
    this.gender = gender;
    MyPerson.sayName = MyPerson.prototype.sayName = function (obj) { // 在自己的prototype空间里写函数
    obj = obj || this;
    console.log("大家好,我系" + obj.name + ", 一只火眼金睛的" + obj.gender); // 让每个实例都能访问
    }
    }
    var mp1 = new MyPerson("孙悟空", 2000, "男猴"); // 注意这里使用的是new MyPerson,构造
    mp1.sayName();
    MyPerson.sayName(mp1);
  • 相关阅读:
    C# 中字符串转换成日期
    c#中退出WinForm程序包括有很多方法,如:this.Close(); Application.Exit();Application.ExitThread(); System.Environment.Exit(0);
    c#获取程序版本号
    分分钟用上C#中的委托和事件
    【转载】C# 中的委托和事件(详解:简单易懂的讲解)
    C#什么时候需要使用构造函数
    15、生命周期-BeanPostProcessor-后置处理器
    13、生命周期-InitializingBean和DisposableBean
    11、组件注册-使用FactoryBean注册组件
    12、生命周期-@Bean指定初始化和销毁方法
  • 原文地址:https://www.cnblogs.com/kuaizifeng/p/9293408.html
Copyright © 2020-2023  润新知