• JS学习笔记


    镇楼图

    Pixiv:DSマイル

    备注:写得比较简略



    〇、JS基本语法

    利用JS可以使网页具备交互能力,有关JS的历史不在此说明(可能会看到DHTML或是ES、TS等其他概念或是技术,但不在此说明)

    JS属于解释性语言,主要由ECMAScript、DOM、BOM三部分组成

    JS代码使用方式

    <script>
        //内嵌式
    	//这里开始写JS代码
    </script>
    
    <script src="JS文件位置"></script>
    <!-- 外部式 -->
    
    <!-- 行内式 -->
    <input type="button" onclick="//JS代码">
    

    语句

    JS的语法非常自由,可以加分号也可以不加分号

    s1
    s2;
    //推荐加分号
    

    注释

    JS的注释和C语言一样,采用///**/<!--

    <!-- 我是注释1,不需要添加"-->"
    //注释2
    /*
    	注释3
    */
    

    输入/输出

    var x = prompt("输入");
    //prompt输入的为String类型
    alert("弹出警告框");
    console.log("浏览器控制台输出,F12可看到")
    

    变量

    JS是弱类型的语言,且大小写敏感,命名规则不再说明和其他语言一样

    var age = 18;
    age = "18岁"
    

    JS的语法是非常随意的,甚至类型都是可以随意变换的(术语称为动态类型),可以一会字符串一会数字

    数据类型

    在JS中有七种数据类型,这里先说明五种,其他类型后续会说明

    var a;
    //undefined类型
    //表明已声明但未赋值
    
    var b = null;
    //NULL类型
    /*对于字符串拼接运算而言
      null会当作空字符串
      而其他像是undefined、true都会当作实际的字符串值
    
    var c = true;
    var d = false;
    //Boolean类型
    //与数值运算时true当作1,false当作0
    
    var e = "String类型";
    //备注:JS同样存在转义字符
    //可以用单引号也可以用双引号
    
    var g = 114514;
    g = 1.14514;
    //Number类型
    //无需区分整数、浮点数
    var h = 0114;
    //前面加0表示八进制
    var i = 0x514;
    //前面加0x表示十六进制
    var j = Infinity;
    var k = NaN;
    //其中有两类特殊数值
    //Infinity,-Infinity表示正/负无穷
    //NaN表示非数字,如字符串或是无法运算的不是数字,可以用isNaN(k)判断
    

    转换为String

    toString(a);
    String(b);
    "" + 123;//可以通过拼接运算隐式转换
    

    转换为Boolean

    Boolean(NaN);
    //'',0,NaN,null,undefined会转成false
    //其余都会转成true
    

    转换为Number

    parseInt("1.114514");
    //转换为整数
    parseFloat("1.114514");
    //转换为浮点数
    Number("11451.4");
    alert('100' * 10);
    //可以过算术运算- * /隐式转换
    //备注:不会转成ASCII码再运算
    

    运算

    运算符(没有按照优先级排列) 说明
    typeof 获取某一类型、变量等的类型
    + 字符串拼接运算
    + - * / % 加减乘除余
    ++ -- 自增/减,先增减还是先返回和C语言一样略
    < > <= >= == != === !== 比较,唯一不同的是在判断相等/不等时有不同的运算符(见备注)
    && || ! 与或非,备注:存在短路判断机制
    = += -= *= /= %= 赋值运算符
    ,
    (条件) ? v1 : v2 条件,三元运算符

    备注:

    在JS中比较相等/不等时有两类

    ■!= ==,这种是不严格比较,不会比较数据类型会先隐式转换成相同的数据类型(好像是转换成Number)再进行判断

    ■!== ===,这种是严格比较,会比较数据类型,只要类型不同就会返回false

    流程

    这和大部分语言一样,这里就不再说明

    if(/*条件*/){
        //
    }
    
    if(/*条件*/)/*s1;*/
    
    if(/*条件*/){
    	//
    } else{
    	//
    }
    
    switch (/*表达式*/){
        case v1:
            //
            break;
            //continue略
        case v2:
            //...
            break;
    	//...
        default:
            //...
    }
    
    while(/*条件*/){
    	//...
    }
    
    do{
        //...
    }while(/*条件*/);
    
    for(/*初始*/;/*条件*/;/*步长*/){
        //...
    }
    

    数组

    由于JS是动态类型,因此数组显得相当灵活,其下的元素类型可以完全不同

    a = new Array(4);
    //创建长度为4的数组
    b = Array();
    //可不声明长度和new
    var c = Array("字符串",true,a,b,123);
    //可以在直接定义元素
    //且其中元素类型可以完全不同
    d = ["字符串",514];
    e = [];
    //这是另一种定义方式
    y[0] = 114;
    //索引方法
    

    JS的索引(下标)默认是从0开始的数字,但其实可以更加灵活,像是用哈希表一样,索引也是任意的

    x = [];
    //通过如下方式可以添加元素
    x["name"] = "Li Hua";
    x["year"] = 15;
    x[12] = 100;
    x[false] = 123;
    alert(x[false]);
    
    s1 = Array();
    s2 = Array();
    s3 = Array();
    f = [s1,s2,s3];
    s1["X"] = 25;
    alert(f[0]["X"]);
    //也可以构成多维数组
    
    //可以用数组length来调用或修改
    a = [];
    a["20"] = 20;
    a["10"] = 10;
    a["00"] = 0;
    a.length = 6;
    alert(a);
    //此时a只有3个定义的元素,其余的会视为empty
    

    函数

    function name(/*参数表*/){
    	//...
    	//return 返回值;
    }
    //JS中如果不写return则认为return undefined;
    
    
    function f(n = 5){
        //指定默认值
        if(n === 1)return 1;
        else return n*f(n-1);
    }
    
    f();
    /*在不指定默认值的情况下
    是允许不用传递参数的
    但此时视为undefined
    输出多半会是奇怪结果
    

    arguments定义可变参数

    arguments是一种伪数组,伪数组同样可以用length属性获取长度,但缺少很多数组里的方法

    function add(){
        //会在Arguments数组存储所有传递的值
        var sum = 0;
        for(var i = 0;i < arguments.length;i++){
    		sum += arguments[i]; 
        }
        return sum;
    }
    
    var x = add(1,2,3,4,5);
    alert(x);
    

    其他定义方式

    var m1 = function(a,b,c){
        //称为匿名函数
        return a+b+c;
    }
    var m2 = [];
    m2[1] = m1;
    alert(m2[1](1,2,3));
    //现在可以通过变量名来调用
    

    作用域

    在JS中同样有作用域的概念,在函数外的变量为全局作用域(适用当前js文件),在函数内的为局部作用域(适用当前函数)

    备注:无块级作用域(ES6有)

    a = 1;
    //全局变量
    function f(){
        alert(a++);
    }
    
    f();
    f();
    

    作用域链

    JS是允许函数内写函数的,其中子级的函数可以用父级的变量或是函数

    至于先调用哪个会从当前一级往上寻找(就近原则),如果没有就报错

    function f1(){
        var n = 10;
        function f2(){
            alert(f3(n));
        }
        function f3(n){
            return n;
        }
    	f2();
    }
    
    f1();
    

    预解析

    JS是解释型语言,即会从上到下逐句解析,但在解析之前会进行一步预解析

    预解析过程中会将所有var、function提升到当前作用域最前面,然后根据输入顺序从上到下执行

    其中对变量来说,从上到下如果运行到之前为遇到的变量就视为undefined

    alert(f(5));//正常
    function f(a){
        return a;
    }
    alert(a);//报错
    a = 5;
    alert(b);//正常,但有问题
    var b = 6;
    //变量只会预解析声明
    //但不会预解析赋值因此是undefined
    
    //=========================
    var n = 10;
    f();
    function f() {
        alert(n);//结果为undefined
        //函数中的var n会提前
        //但其赋值不会提前
        var n = 20;
    }
    

    Web APIs

    在简单了解JS语言特性以及DOM后一方面可以接着深入ES,令一方面可以开始着手Web APIs。我个人是优先倾向于后者,ES可能要再等一段时间才会学习。

    其中DOM、BOM(WOM)是Web APIs中特别重要的一环,是直接实现交互功能的关键

    API是指应用程序编程接口(Application Programming Interface),预先提供了一定功能可以直接实现功能而不需要考究源码


    一、面向对象(Object)

    Object

    Object是特别重要的一类数据类型

    Object由属性、方法组成

    在JS中分为三类

    ■用户定义对象:用户自行创建的对象

    ■内建对象:JS中自带的(写在了我的其他blog中,这里不再说明)

    ■宿主对象:其他运行环境中自带的

    对象类型的某一个变量称为实例

    var x = Object();
    //创建尚未定义的对象
    x.status = 0;
    //设定属性
    var a = new x;
    //通过new生成实例
    

    创建/调用

    var x = {};
    //创建空对象
    var y = {
        name: 1,
        age: 18,
        BP: 3000,
        test: function(){
            alert("test");
        }
    }
    //可以创建具有属性方法的对象
    alert(y.age);
    alert(y['BP']);
    //备注:这种形式必须用String进行索引
    //调用属性
    y.test();
    //调用方法
    
    var obj = new Object();
    //创建空对象
    
    function obj1(name,age){
        this.name = name;
        this.age = age;
    }
    //构造对象类型
    var a = new obj1('张三',18);
    //可以通过new来调用定义对象
    

    遍历对象

    for(var x in obj){
        alert(obj[x]);
        //通过for in的形式
        //x可以依次获取其属性名
    }
    

    二、DOM(Document Operate Moudle)

    通过DOM接口可以访问HTML所有的元素,当网页加载时便会产生DOM

    有关DOM的具体内容我已写在其他blog,这里主要介绍最常用的

    DOM树

    以一种树结构来看到HTML文档,会发现本质上是有迹可循的,从树结构也能够更好地运用CSS选择器

    DOM中有非常多的对象最重要的是document对象,有一类特别的对象称为window称为BOM(WOM),这种对象是网页整体的页面

    通过转换对象后,可以通过属性或是方法去改变实现网页的动态变化

    再DOM树下某一元素中又分成了许多节点。节点可以是元素、属性、文本等一切内容

    获取元素

    要控制HTML元素首先要找到才能去使用

    alert(typeof document.getElementById("element1"));
    //返回id为element1的对象
    
    document.getElementsByTagName("li");
    //返回标签为li的对象数组
    var y = document;
    var item = y.getElementsByTagName("p")[2];
    //获取p标签的对象数组的第三个对象
    var z = document.getElementsByTagName("*");
    alert("总元素数:"+z.length);
    
    document.getElementsByClassName("class");
    //返回类名为class的对象数组
    document.getElementsByClassName("class1 class2");
    //返回具有class1和class2两个类名的对象数组
    
    document.querySelector('选择器名');
    //根据指定选择器返回第一个元素对象
    

    获取其他元素对象

    //可以直接根据元素名来获取
    document.body
    //返回body元素对象
    document.documentElement
    //返回html元素对象
    

    有关元素属性常用方法

    找到后便可以进行和浏览器元素属性有关的操作,使得浏览器“动起来”

    object.getAttribute(attr);
    //返回object的属性attr
    var p = document.getElementsByTagName("p");
    for(var i = 0;i < p.length;i++){
    	var text = p[i].getAttribute("title");
        //var text = p[i].title;
        //利用属性而非方法实现也是可以的
        if(text != null) alert(text);
    }
    //获取每个p元素的title属性
    //注:对于不存在的属性值会返回null
    
    object.setAttribute(attr,value)
    //设置元素属性值
    
    var ol = document.getElementsByTagName("ol");
    for(var i = 0;i < ol.length;i++){
    	ol[i].setAttribute("type","i");
    }
    //将所有ol元素的type改成i
    
    var p = document.getElementsByTagName("p");
    p[0].setAttribute("title","");
    //属性值设为空
    p[0].title="";
    //利用属性而非方法实现也是可以的
    

    事件

    要触发JS代码,需要触发-响应机制,即只有满足一定条件时才会触发

    事件由三部分组成

    事件源、事件类型、事件处理(js代码)

    事件源要触发事件的对象,可以是文本、图像、按钮之类的载体

    事件类型有很多,这里不作具体说明

    事件处理就是之后要执行的js代码

    <img src="1.png" alt="..." onclick="test(this);" />
    <!-- 
    	onclick是鼠标点击事件
    	里面的属性值是JS代码
    	如这里触发了test(this);
    -->
    
    <a href="1.html" onclick="return false" id="aaa">打不开QAQ</a>
    <!--如果返回false则链接不会被打开-->
    

    当然这里还是繁琐了些,可以直接写在js代码中

    混着HTML还可能混着CSS我个人是不太喜欢

    var x = document.getElementById("aaa");
    
    x.onclick = function(){
        return false;
    }
    //1.获取事件源
    //2.定义事件
    //3.编写js代码
    

    改变元素内容

    element.innerText
    //文本,不可识别标签
    //不保留空格换行
    element.innerHTML
    //HTML,可识别标签
    //保留空格换行
    
    var div = document.querySelector("div");
    function f(){
        div.innerText = '123456';
        //改变div元素内容
    }
    function g(){
        div.innerHTML = '<b>123</b>456';
        //可以识别HTML标签
    }
    

    改变样式

    element.style.xxx = '';
    //可以通过style简单设置样式,但命名有所区别
    //如grid-gap在JS要用驼峰命名即gridGap来指定
    //JS产生的是行内样式,因为优先级特别高
    
    element.className = '';
    //更改某一元素的类名
    

    节点操作

    一个节点有nodeType、nodeName、nodeValue三个基本属性

    节点类型分成了元素节点(nodeType=1)、属性节点(nodeType=2)、文本节点(nodeType=3)

    //通过节点操作能更方便的获取元素
    node.parentNode
    //获取父节点
    node.childNodes
    //获取所有子节点对象的集合
    //备注:除了元素节点不要忽略其他类型节点
    //可以通过nodeType属性进行处理
    node.children
    //获取所有子元素节点对象的集合
    node.firstChild
    node.lastChild
    //获取子节点中第一个/最后一个节点
    node.firstElementChild
    node.lastElementChild
    //获取子节点中第一个/最后一个元素节点
    node.nextElementSibling
    //获取当前节点的下一个兄弟节点
    
    document.createElement("tag");
    //动态创建tag元素节点
    node.appendChild(child);
    //在node元素下在最后追加子节点
    node.insertBefore(child,x);
    //插入child元素至node父元素下x之前
    node.removeChild(child);
    //删除node下某一child子节点
    var x = node.cloneNode();
    var x = node.cloneNode(false);
    //浅copy,只复制标签不复制内容
    var x = node.cloneNode(true);
    ///深copy,复制标签和内容
    

    对于创建内容来说,总体上innerHTML(采用数组)的效率要高于createNode

    事件

    注册事件有两种方式:传统方式与监听注册

    传统方式对同一元素同一事件设置唯一的处理函数

    监听注册(推荐)采用addEventListener()对同一元素同一事件可以设置多个监听器

    btn.addEventListener(事件,处理函数,useCapture);
    //useCapture可选参数,默认false
    //采用监听方式可以设置多个
    //传统方式只能设定唯一的监听器
    //监听器方式事件与传统方式略有区别,具体参考MDN
    

    此外可以删除事件

    btn.onclick = null;
    //传统方式只要对某个事件设置null即可删除
    btn.removeEventListener(事件,处理函数,useCapture);
    //监听器方式采用removeEventListener
    //useCapture可选参数,默认false
    

    DOM事件流:事件流是指页面接受事件的顺序,事件发生时会在元素节点之间按照某顺序进行传播,这个传播过程就是DOM事件流

    捕获阶段:首先需要从上到下捕获要定义事件的元素

    当前目标阶段:处理事件

    冒泡阶段:再返回到顶层

    JS代码只能执行捕获或是冒泡中的一个阶段,其中useCapture可选参数分别表示了捕获阶段(true)和冒泡阶段(false)

    btn.addEventListener('click',function(){return false;},true);
    //表明再捕获阶段调用
    

    这用于定义嵌套元素且每层都有事件时的执行事件的顺序

    如果是捕获阶段,那么会从父元素到子元素执行,如果是冒泡阶段那么会从子元素到父元素执行



    参考书籍

    《JavaScrpit DOM 编程艺术》

    参考网站

    MDN

    参考教程

    黑马程序员 JS pink

  • 相关阅读:
    辛星浅析跨域传输的CORS解决方式
    Hadoop HDFS (3) JAVA訪问HDFS
    【多线程】将大批量数据插入多张表,怎么知道多张表都插成功了
    【sublime text 3】sublime text 3 汉化
    【spring data jpa】使用spring data jpa时,关于service层一个方法中进行【删除】和【插入】两种操作在同一个事务内处理
    【spring data jpa】使用spring data jpa 的删除操作,需要加注解@Modifying @Transactional 否则报错如下: No EntityManager with actual transaction available for current thread
    【spring mvc】后台的API,测试中,总提示接口实体的某一个字段不能为null,但是明明给值了还提示不能为空
    【postman】postman测试API报错如下:TypeError: Failed to execute 'fetch' on 'Window': Invalid value 对中文支持不好
    【spring mvc】后台spring mvc接收List参数报错如下:org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.util.List]: Specified class is an interface
    【java】Java transient关键字使用小记【转】
  • 原文地址:https://www.cnblogs.com/AlienfronNova/p/16177269.html
Copyright © 2020-2023  润新知