JavaScript文档总结篇

JavaScript基础

1、控制台输出
  • console里面的内容方法非常丰富,你可以在控制台输入 console,然后就可看到
    • console.warn:输出警告信息
    • console.error:输出错误信息
    • console.assert:参一为boolean、参二为输出信息,当参一为false时输出错误信息
    • console.debug:用于调试信息
    • console.table:以table形式输出
    • console.time() & console.timeEnd():计算代码执行时间
    • console.trace():输出函数调用栈(用于调试调用资源)
    • console.clear:清空控制台所有输出
    • console.(console.memory):查看当前内存的使用情况
2、Javascript的数据类型
  • JS的数组的判断方法(数组本质上是特殊类型的对象)

    typeof([1]) // Object
    Array.isArray([1]) // true
    console.log([1] instanceof Array) //true
    
  • 基本数据类型的变量是放在栈内存(stack)里面的,包括变量的标识符和变量的值

  • 引用数据类型的值是放在堆内存(Heap)里面的(Object)

    • 栈内存存放引用数据变量的标识符和引用的内存地址
    • 堆内存存放变量值的对象内容
  • 将任何数据转化为布尔值:!!

3、JavaScript的对象
  • 访问对象除了person.name还有person[“name”]

    • 使用[]访问,中括号访问会把动态变量转换为实际的变量

    • 当所取得键名是一个特殊的字符串时,只能用[ ]不能用 .

      var person={
      	name:'张三',
          "sex":'男'
      }
      
      var x=name;
      person.x //会到对象里寻找属性名为x的属性值,为undefined
      person[x] //会把x转化为name到对象里寻找,为张三
      person.sex //为undefined
      person["sex"] //为男
      
  • 同一个对象出现相同的属性名,那么属性值会以最后一个出现的为准(覆盖)–> 联系展开运算符的使用

4、Javascript的函数
  • 局部变量会在函数执行之后被删除,全局变量会在页面关闭之后被删除
  • 如果把值赋给了尚未声明的变量,该值自动作为window的一个属性,可配置,可删除
    • 如果变量在函数里面未声明就赋值也会变成全局变量(非严格模式)
    • 所有全局变量都归属于window对象
  • **高内聚是说模块内部要高度聚合,低耦合是说模块与模块之间的藕合度要尽量低。**前者是说模块内部的关系,后者是说模块与模块间的关系。(严于律己,宽以待人)
5、JavaScript字符串
  • 反斜杠(\)是一个转义字符。 转义字符将特殊字符转换为字符串字符,可以用于转义撇号,换行,引号,等其他特殊字符。
  • 字符串的常用方法
    • concat():返回拼接后字符串
    • indexOf():返回查找的第一个目标字符串的索引
    • replace():正则替换
    • slice():返回提取的片段
    • split():分割字符串为数组
    • trim():移除首尾空白
  • 模板字符串支持多行文本,而无需使用特殊的转义字符
6、JavaScript for 循环
  • for/in 用来遍历对象(遍历较慢,不利于性能

    for (x in person)  // x 为属性名
    {
        txt=txt + person[x];
    }
    
  • for/of(来自ES6)用来遍历数组、字符串、Map、Set,不能直接遍历普通对象

    const fruits = ['apple', 'banana', 'orange']; // 数组
    for (const fruit of fruits) {
      console.log(fruit);
    }
    
    const str = 'hello'; // 字符串
    for (const char of str) {
      console.log(char);
    }
    
    const map = new Map(); // Map对象
    map.set('name', '张三');
    map.set('age', 30);
    for (const [key, value] of map) {
      console.log(`${key}: ${value}`);
    }
    
    const set = new Set([1, 2, 3]); // Set对象
    for (const num of set) {
      console.log(num);
    }
    
7、JavaScript的typeof
  • typeof null的结果为object,undefined和null值相等但类型不同

    typeof undefined             // undefined
    typeof null                  // object
    null === undefined           // false
    null == undefined            // true
    
  • null:主动释放一个变量引用的对象,表示一个变量不再指向任何对象地址

    • 何时使用:当使用完一个比较大的对象时,需要对其进行释放内存时,设置为 null
  • 垃圾回收站–>专门释放对象内存的一个程序

    • 在底层,后台伴随当前程序同时运行;引擎会定时自动调用垃圾回收器
    • 当一个对象没有被任何变量引用时会被释放
8、JavaScript的类型转换
  • NaN:number

    • 用于本来要返回数值的操作数但未返回数值的情况
    • NaN与任何值都不相等,包括NaN本身
    • isNaN() 方法来判断某个数值是否是NaN这个特殊的数
  • Date、Array、null:object。判断具体类型可以通过instanceof

  • 转换为string的全局方法

    • String()
    • toString()
  • 转换为number的全局方法

    • Number()
    • 一元运算符+可将变量转换为number类型,如果是转换不了为数字的变量,则结果为NaN
    • parseInt()和parseFloat()
  • string与number做加法运算–>number会隐式转换为string

  • string与number做减法运算–>string会隐式转换为number

  • 可以使用typeof判断变量是否存在

    if(typeof x != undefined){...}
    // 替换下面这种方法
    if(x){...} // 如果a为undefined的话会报错
    
9、JavaScript 正则表达式
  • 语法格式:/正则表达式主体/可选修饰符

  • 字符串方法search:用于检索字符串的指定子字符串,返回其起始索引

    var n = str.search(/Runoob/i); // 参数为字符串或正则表达式
    
  • 字符串方法replace:用于替换字符串的指定子字符串,返回新的字符串

    var txt = str.replace(/microsoft/i,"Runoob");// 替换microsoft为Runoob
    
  • text()方法为正则表达式的方法,用于检测字符串是否含有该正则的文本,返回Boolean

    /e/.text("The best things in life are free!")
    
10、JavaScript调试
  • 设置断点,在每个断点上都会停止执行代码,方便我们检查变量的此时的值,检查完毕可以重新执行代码
  • debugger关键字用于停止执行JS,效果与断点一致
11、JavaScript变量提升(Hoisting)
  • 声明提升:函数声明和变量声明总是在代码执行前会被解释器悄悄地被"提升"到方法体的最顶部。

  • 变量声明提升:变量只有声明部分会提升,赋值(初始化)部分则保留在原地。

    var x = 5; // 初始化 x
    var y = 7; // 初始化 y  (x和y本来就在顶部,不需要提升)
    elem = document.getElementById("demo"); // 查找元素
    elem.innerHTML = x + " " + y;           // 显示 :5 7
    
    var x = 5; // 初始化 x
    elem = document.getElementById("demo"); // 查找元素
    elem.innerHTML = x + " " + y;           // 显示:x undefined
    var y = 7; // 初始化 y
    // 这里声明部分(var y)提升了,但是初始化(y=7)不会提升
    
  • 函数声明提升

    • 使用函数function foo(){…}:函数声明和初始化都会提升
    • 使用表达式var foo= function (){…}:仅提升声明部分,表达式被留在原地
  • ES6 引入的 letconst 也有提升,但表现不同 - 它们存在"暂时性死区"

    • 暂时性死区:从作用域开始到 let/const 变量声明语句执行之前的区域,在这期间访问该变量会抛出错误
  • JavaScript 严格模式(strict mode)不允许使用未声明的变量。

12、JavaScript严格模式
  • 严格模式通过在脚本或函数的头部添加 use strict; 表达式来声明。

  • 在函数内部声明是局部作用域 (只在函数内使用严格模式)

    x = 3.14;       // 不报错(此时函数外部严格模式无效)
    myFunction();
    
    function myFunction() {
       "use strict";
        y = 3.14;   // 报错 (y 未定义)
    }
    
  • 严格模式下,禁止this指向全局对象

    function f(){
        return !this;
    } 
    // 返回false,因为"this"指向全局对象,"!this"就是false
    
    function f(){ 
        "use strict";
        return !this;
    } 
    // 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。
    
  • 因此,使用构造函数时,如果忘了加new,this不再指向全局对象,而是报错

    // 情况一:
    function f() {
        "use strict";
        this.a = 1;
    }
    f(); // ❌ TypeError: Cannot set property 'a' of undefined
    
    // 情况二:
    function f() {
        "use strict";
        this.a = 1;
    }
    const obj = new f(); // ✅ 正常执行
    console.log(obj.a); // 1
    
    • 严格模式下,普通函数调用时 thisundefined(非严格模式下是 window–>被提升)
    • new 操作符会使 this 指向一个新创建的空对象,无论是否严格模式
13、JavaScript的误区
  • JavaScript 中的所有数据都是以 64 位浮点型数据(float) 来存储
  • JavaScript 的 **自动分号插入(ASI)**让return默认只作用于本行内容,需要作用于多行时可以使用括号包裹、使用模板字符串、数组、对象等
  • 许多程序语言都允许使用名字来作为数组的索引。使用名字来作为索引的数组称为关联数组(或哈希)。但是JavaScript 不支持使用名字来索引数组,只允许使用数字索引。
14、JavaScript表单
  • JavaScript实现表单验证

    <form name="myForm" action="demo_form.php" onsubmit="return validateForm()" method="post">
    名字: <input type="text" name="fname">
    <input type="submit" value="提交">
    </form>
    
    <script>
    	function validateForm() {
            // document.forms就可以获取表单啦!	
            var x = document.forms["myForm"]["fname"].value;
            if (x == null || x == "") {
                alert("需要输入名字。");
                return false;
            }
        }
    </script>
    // document.forms["myForm"]根据表单的name得到表单
    
  • 浏览器也会支持HTML的表单验证的自动验证,如果有字段为空,required属性会阻止表单提交

  • HTML5 提供了一些内置的表单验证功能,例如 requiredpatternminmax 等属性。

15、JavaScript的this
  • 一个区别:在面向对象里面,this指当前对象的一个引用,但是在JavaScript里面,this的指向并不是不变的

    • this 的值取决于函数的调用方式,而不是定义位置

    • 全局环境中,this指向全局对象(浏览器指向window、Node环境指向global)

    • 普通函数this指向全局对象(不需要关注普通函数定义的位置,只要它不是对象的直接方法就行)

      const obj = {
        name: '张三',
        greet: function() {
          setTimeout(function() {
            console.log('你好,我是' + this.name);
          }, 100);
        }
      };
      
      obj.greet(); // 输出 "你好,我是undefined"(因为回调函数的this指向window)
      // 在定时器里面的那个函数并不是对象的方法,所以this没有指向该对象,而是指向全局对象
      
    • 在严格模式下,在函数中的this为undefined,单独使用this的话依旧指向全局对象

    • 函数作为对象的方法调用时,this指向调用该方法的具体对象

    • 使用new调用构造函数时,this指向新创建的实例

    • 在DOM事件处理函数中,this指向触发事件的元素

    • 箭头函数没有this,他会捕获所在上下文的this

  • 在JavaScript中函数也算是对象,是对象就有方法,apply和call是函数对象异常强大的两个方法,他们允许显式切换函数执行的上下文环境(context),即this绑定的对象

    var person1 = {
      fullName: function(greeting,punctuation) {
        return greeting + ', ' + this.name + punctuation; //本来this指向person1
      }
    }
    var person2 = {
      name:'张三'
    }
    // call使this指向person2
    person1.fullName.call(person2,'你好''!');  // "你好张三!"
    
    • func.call(thisArg, arg1, arg2, …):参数一为指定的this,后续参数为函数的参数列表
    • func.apply(thisArg, [argsArray]):参数一为指定的this,后续参数为包含参数的数组
16、JavaScript JSON
  • JSON数据格式通常用于服务端向网页传输数据,全称 JavaScript Object Notation

  • JSON 格式在语法上与创建 JavaScript 对象代码是相同的。所以两者很容易互相转化

    {"sites":[
        {"name":"Runoob", "url":"www.runoob.com"}, 
        {"name":"Google", "url":"www.google.com"},
        {"name":"Taobao", "url":"www.taobao.com"}
    ]}
    
  • 转化方法

    • JSON.parse():JSON—>JavaScript对象
    • JSON.stringify():JavaScript—>JSON
17、JavaScript void
  • 特殊的表达式,主要用于阻止默认行为(如链接跳转)而不执行任何操作

    // 阻止链接跳转
    <a href="javascript:void(0)" onclick="myFunction()">点击执行JS但不跳转</a>
    // 	比 href="#" 更好(不会滚动到页面顶部)
    
    // 阻止默认提交表单
    <form onsubmit="javascript:void(0); return false;">
      <button type="submit">提交</button>
    </form>
    
    // 作为无副作用的占位符
    const result = condition ? doSomething() : void(0);
    

JavaScript函数、类

1、函数定义
  • 不同形式函数的存储位置

    // 函数表达式
    var x = function(a, b) { return a * b };// 这也是匿名函数
    // 存储在变量x的值中
    // 函数提升只提升声明,不提升函数体
    
    // 函数声明
    function multiply(a, b) { return a * b }
    // 存储在当前作用域的变量环境中,相当于 => var multiply= function(){...}
    // 函数可以整体提升(声明+函数体),可提前调用
    
    // 立即执行函数
    (function(a, b) { return a * b })(2, 3);
    // 不存储于任何变量中
    // 执行后函数对象会被垃圾回收(除非返回的值被其他变量引用)
    
  • 函数同样可以通过内置的 JavaScript 函数构造器(Function())定义

    var myFunction = new Function("a", "b", "return a * b");
    // 但是建议尽量少用new
    
  • toString() 方法可以将整个函数作为一个字符串返回

  • 箭头函数的匿名自调用为 (()=>{})() ,箭头函数的this默认绑定外层的this

2、JavaScript函数参数
  • 显式参数(Parameters):函数定义时声明的命名参数

  • 隐式参数通过(arguments)访问,是一个类数组,包含所有传入的参数

    function sum() {
      let total = 0;
      for(let i = 0; i < arguments.length; i++) {
        total += arguments[i];
      }
      return total;
    }
    console.log(sum(1, 2, 3)); // 6
    
    //arguments.length为函数实参个数
    //arguments.callee引用函数自身
    
  • 箭头函数没有arguments,arguments只接收调用函数时传入的参数,不接收默认值

3、JavaScript函数调用
  • this代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。随着函数使用场合的不同,this 的值会发生变化。但是有一个总的原则,那就是this指的是,调用函数的那个对象

  • 一个函数的this如果指向全局对象的话,那么调用这个函数也可以用:window.函数名()

    • 所以区分是不是指向window,看一下能不能使用window.函数名()调用即可
  • 如果函数调用前使用了 new 关键字, 则是调用了构造函数。就像创建了新的函数,但实际上 JavaScript 函数是重新创建的对象。构造函数的调用会创建一个新的对象。新对象会继承构造函数的属性和方法。下面是一个实例

    // 定义一个构造函数
    function myFunction(arg1, arg2) {
        this.firstName = arg1;
        this.lastName  = arg2;
    }
     
    // 使用new关键字 调用构造函数  就像是创建了一个新的对象
    var x = new myFunction("John","Doe");
    x.firstName;                             // 返回 "John"
    
  • 一个有趣的函数:调取页面所有图片的url

    [].map.call(document.getElementsByTagName('img'), function (img){ return img.src;})
    
4、JavaScript闭包
// 一个闭包函数
var add = (function (){
    var count=0;
    return function (){count+=1}
})

add()
add()
add()  //此时count=3
  • 以上自我调用函数只执行一次。设置计数器为 0。并返回函数表达式存储在变量add中,add变量可以作为一个函数调用,并且可以访问上一层作用域的count。这个就叫做JavaScript闭包,它使函数拥有私有变量变成可能。闭包是一种保护私有变量的机制,它在函数执行时创建一个私有作用域,从而保护内部的私有变量不受外界干扰。直观地说,闭包就像是一个不会被销毁的栈环境。闭包就是一个函数引用另一个函数的变量,致使被引用的变量不会被回收,因此可以用来封装成一个私有变量。这是优点也是缺点,不必要的闭包只会增加内存消耗

  • 闭包三要素

    • 外层函数
    • 外部变量(count)
    • 内层函数(引用外层函数的外部变量count)
  • 闭包允许你创建真正的私有变量(数据封装)

    function createCounter() {
        let count = 0; // 私有变量
        
        return {
            increment: function() { count++; },
            getCount: function() { return count; }
        };
    }
    
    const counter = createCounter();
    counter.increment();
    console.log(counter.getCount()); // 1
    console.log(counter.count);      // undefined(无法直接访问)
    
  • 闭包使得函数可以"记住"并访问其词法作用域中的变量,即使函数在其词法作用域之外执行

    function makeGreeter(greeting) {
        return function(name) {
            return `${greeting}, ${name}!`;
        };
    }
    
    const sayHello = makeGreeter("Hello");
    const sayHi = makeGreeter("Hi");
    
    console.log(sayHello("Alice")); // "Hello, Alice!"
    console.log(sayHi("Bob"));      // "Hi, Bob!"
    
  • 闭包是实现模块模式的基础,可以创建独立的、可复用的代码单元

    const calculator = (function() {
        let memory = 0;
        
        function add(a, b) { return a + b; }
        function store(value) { memory = value; }
        function recall() { return memory; }
        
        return {
            add,
            store,
            recall
        };
    })();
    
    console.log(calculator.add(2, 3)); // 5
    calculator.store(10);
    console.log(calculator.recall());  // 10
    
  • 闭包可以帮助你减少全局变量的使用,防止命名冲突

    // 不使用闭包(污染全局)
    let count = 0;
    function increment() {
        count++;
    }
    
    // 使用闭包(不污染全局)
    const counter = (function() {
        let count = 0;
        return {
            increment: function() { count++; },
            getCount: function() { return count; }
        };
    })();
    
  • 闭包使得函数可以返回函数,这是函数式编程的基础

    function multiplyBy(factor) {
        return function(number) {
            return number * factor;
        };
    }
    
    const double = multiplyBy(2);
    const triple = multiplyBy(3);
    
    console.log(double(5)); // 10
    console.log(triple(5)); // 15
    
  • 闭包在异步编程中非常有用,可以保留回调函数执行时所需的上下文

    function setupButtons() {
        for (var i = 1; i <= 3; i++) {
            (function(index) {
                document.getElementById(`btn-${index}`)
                    .addEventListener('click', function() {
                        console.log(`Button ${index} clicked`);
                    });
            })(i);
        }
    }
    
  • 闭包可以用来缓存昂贵的计算结果,提高性能,实现缓存和记忆化

    function createMemoizedFibonacci() {
        const cache = {};
        
        return function fib(n) {
            if (n in cache) return cache[n];
            if (n <= 1) return n;
            
            cache[n] = fib(n - 1) + fib(n - 2);
            return cache[n];
        };
    }
    
    const fib = createMemoizedFibonacci();
    console.log(fib(10)); // 55(快速返回,因为有缓存)
    
  • 缺点:闭包会保持对私有变量的引用,导致内存无法释放,并且创建大量闭包可能影响性能

  • 解决思路:在闭包里面返回一个函数是让引用变量指向null

5、JavaScript 类
  • 类的构造方法constructor在实例化时自动调用,用于初始化类对象属性

  • 类继承使用extends关键字(底层依旧依赖于原型继承)

    • super()方法用于调用父类的构造函数
    • 继承基类的派生类拥有基类的属性和方法(需调用super方法初始化基类属性)
  • 下面是不使用extends继承,而是直接使用原型继承的过程

    // 定义一个构造函数
    function Animal(name) {
      this.name = name;
    }
     
    // 可以给构造函数的原型上添加一些属性方法
    Animal.prototype.eat = function() {
      console.log(this.name + " is eating.");
    };
     
    // 定义另一个构造函数
    function Dog(name, breed) {
      // 调用Animal类的构造方法,使用call方法使Animal对象的this指向Dog对象
      // 并传入参数调用Animal构造函数的构造方法
      Animal.call(this, name);
      // 定义Dog对象自身的属性
      this.breed = breed;
    }
     
    // 下一步需要建立原型链,让 Dog 继承 Animal
    // 以Animal.prototype为原型创建一个新对象
    // 将 Dog的prototype 指向这个新对象,建立原型链
    Dog.prototype = Object.create(Animal.prototype);
    // 这个时候Dog.prototype.constructor指向的是Animal
    // 我们需要手动改变它的指向,使其指向Dog,完成原型继承
    Dog.prototype.constructor = Dog;
    
    Dog.prototype.bark = function() {
      console.log(this.name + " is barking.");
    };
     
    var dog = new Dog("Buddy", "Labrador");
    dog.eat();  // 调用从 Animal 继承的方法
    dog.bark(); // 调用 Dog 的方法
    
  • 类中我们可以使用 getter 和 setter 来获取和设置值,getter 和 setter 都需要在严格模式下执行

    • 类中添加 getter 和 setter 使用的是 get 和 set 关键字

    • 虽然get和set是方法,但是使用时不需要加 ()

    • getter/setter 方法的名称不能与属性的名称相同,建议使用**下划线 _ **区分

      class Runoob {
        constructor(name) {
          this._sitename = name;
        }
        set sitename(x) {
          this._sitename = x;
        }
        get sitename() {
          return this._sitename;
        }
      }
       
      let noob = new Runoob("教程");
      noob.sitename = "RUNOOB"; // 相当于调用了set方法
      document.getElementById("demo").innerHTML = noob.sitename; // 调用get方法
      
  • 函数声明和类声明之间的一个重要区别在于, 函数声明会提升,类声明不会

  • static修饰的静态方法

    • 使用 static 关键字修饰的方法,又叫类方法,属于类的,不会给到实例化对象上,在实例化对象之前可以通过 类名.方法名 调用静态方法。

    • 静态方法不能在实例化的对象上调用,只能在类中调用

      class Runoob {
        constructor(name) {
          this.name = name;
        }
        static hello() {
          return "Hello!!";
        }
      }
       
      let noob = new Runoob("Runoob");
       
      // 可以在类中调用 'hello()' 方法
      document.getElementById("demo").innerHTML = Runoob.hello();
       
      // 不能通过实例化后的对象调用静态方法
      // document.getElementById("demo").innerHTML = noob.hello();
      // 以上代码会报错
      
    • 如果想要在实例化的对象中调用静态方法,可以将该对象作为参数传递给类的静态方法

      class Runoob {
        constructor(name) {
          this.name = name;
        }
        static hello(x) {
          return "Hello " + x.name;
        }
      }
      let noob = new Runoob("Runoob");
      document.getElementById("demo").innerHTML = Runoob.hello(noob);
      
6、JavaScript构造函数和普通函数
  • 构造函数通常以大写字母开头,通过 new 关键字调用,用于创建对象实例
    • 通常会在内部操作 this,并可能通过 this 添加属性/方法
    • 通常会有原型对象(prototype),用于共享方法
    • 默认返回新创建的对象(即 this),除非显式返回一个对象
  • 普通函数通常以小写字母开头,一般直接调用,或作为方法调用
    • 可能没有 this 操作,或直接返回结果
    • 一般不需要原型,返回 undefined 或显式指定的值
  • 如果函数通过 new 调用,内部的 this 会指向新创建的对象;否则 this 指向全局对象(非严格模式)或 undefined(严格模式)。
7、JavaScript new
  • new 是 JavaScript 中用于实例化对象的关键操作符,它基于构造函数创建对象实例

  • 使用new之后发生的事情:

    • 创建一个对象
    • 设置原型:将新对象的 [[Prototype]](即 __ proto __)链接到构造函数的 prototype 属性
    • 绑定this
    • 执行构造函数–> 初始化数据
    • 返回对象
  • 手动实现 new 关键字的作用

    function myNew(constructor, ...args) {
      // 1. 创建新对象并设置原型
      const obj = Object.create(constructor.prototype);
      
      // 2. 执行构造函数并绑定 this
      const result = constructor.apply(obj, args);
      
      // 3. 处理返回值
      return result instanceof Object ? result : obj;
    }
    
    // 使用示例
    const p = myNew(Person, '李四', 30);
    
  • 实例化构造函数时忘记使用new会造成全局污染(因为此时this会指向window)

    解决方案:使用ES6的class语法,强制使用new来实例化对象

  • 缺点:new创建的对象比普通对象更加笨重(需要维护原型链),且V8引擎对普通对象的优化更好

  • 工厂函数

    // 简单工厂函数
    function createPerson(name, age) {
      return {
        name,
        age,
        greet() {
          console.log(`Hello, I'm ${this.name}`);
        }
      };
    }
    
    const person = createPerson('张三', 25);
    person.greet(); // "Hello, I'm 张三"
    //不使用 new 关键字
    //不依赖于 this 绑定
    //不涉及原型继承
    //直接返回一个新对象
    

JavaScript DOM

1、DOM 简介
  • 当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)

  • 通过id、标签名、类名查找元素

    document.getElementById("intrp")  // 通过id
    document.getElementsByTagName("p")  // 通过标签名,可查找多个
    document.getElementsByClassName("intro")  // 通过类名,可查找多个
    
  • 使用标签名和类名查找多个HTML元素时会返回一个伪数组,无法使用真数组方法。可以使用数组原型配合 slice 方法,利用 call,apply,bind 方法将伪数组转为真数组

    var x=document.getElementById("main");
    var y=x.getElementsByTagName("p");
    console.log(x)//在控制台我们可以看到原型proto为NodeList,是伪数组
    console.log(y)//在控制台我们可以看到原型proto为htmlcollection,是伪数组
    
    //伪数组转为真数组的三个方法
    // 获取数组原型的slice方法,将该方法的this指向y,相当于是y调用了slice方法
    console.log(Array.prototype.slice.call(y))  // slice方法不传参会返回完整的数组副本
    console.log(Array.prototype.slice.apply(y))
    console.log(Array.prototype.slice.bind(y)())
    //在控制台我们可以看到原型proto为Array(0),是真数组
    
  • HTMLCollection 对象类似包含 HTML 元素的一个伪数组

    • getElementsByTagName() 方法返回
  • NodeList 对象

    • 由**getElementsByClassName()querySelectorAll()**返回
  • 伪数组是指具有数字索引和 length 属性,但不具备数组方法的对象

    • arguments 对象(函数内部的参数对象)也是伪数组
2、DOM HTML
  • document.write() 可用于直接向 HTML 输出流写内容

    • 对不要在文档(DOM)加载完成之后使用 document.write()。这会覆盖该文档。
    • 如需要使用,应该在页面加载过程中使用
  • 修改 HTML 内容的最简单的方法是使用 innerHTML 属性

  • 如需改变 HTML 元素的属性,请使用:

    // document.getElementById(id).属性=新属性值
    document.getElementById("image").src="landscape.jpg
    
  • 如需改变 HTML 元素的样式,请使用:

// document.getElementById(id).style.property=新样式
document.getElementById("p2").style.color="blue";
document.getElementById("p2").style.fontFamily="Arial";
document.getElementById("p2").style.fontSize="larger";
3、DOM 事件
  • onload 和 onunload 事件会在用户进入或离开页面时被触发

  • onchange 事件常结合对输入字段的验证来使用

  • onmouseover 和 onmouseout 事件可用于在用户的鼠标移至 HTML 元素上方或移出元素时触发函数

  • onmousedown, onmouseup 以及 onclick 构成了鼠标点击事件的所有部分

  • 对于onclick事件写法: οnclick=函数名+(),这是因为onclick 的值是一个 JavaScript 代码字符串,所以你可以直接写代码,需要加括号

  • addEventListener添加事件句柄(注意:不需要使用 “on” 前缀)

    // 直接向DOM添加事件
    document.getElementById("intro").onclick=function(){...}
    
    // 添加事件句柄
    document.getElementById("myBtn").addEventListener("click", function(){...});
                                                                          
    // 当需要传递参数时,可以使用匿名函数里面调用需要参数的函数
    element.addEventKistener("mouseup",function(){myFun(a,b)})
    
    • 可以使用 element.removeEventListener("mousemove", myFunction) 方法来移除事件的监听
    • 完整写法:element.addEventListener(event, function, useCapture),useCapture可选参数默认为false,此时为冒泡传递,改为true时为捕获传递
    • addEventListener() 方法添加的事件句柄不会覆盖已存在的事件句柄
  • 事件冒泡 中,内部元素的事件会先被触发,然后再触发外部元素

  • 事件捕获 中,外部元素的事件会先被触发,然后才会触发内部元素的事件

4、DOM 元素
  • 创建新的HTML元素节点—**appendChild()**方法

  • 如果我们需要将新元素添加到开始位置,可以使用 insertBefore() 方法

  • 移除旧的HTML元素节点—**removeChild()**方法

  • 创建新的元素节点:document.createElement(“标签名”)

  • 创建新的文本节点:document.createTextNode(“文本内容”)

    <div id="div1">
    <p id="p1">这是一个段落。</p>
    <p id="p2">这是另外一个段落。</p>
    </div>
     
    <script>
    var para = document.createElement("p");  // 创建新元素
    var node = document.createTextNode("这是一个新的段落。");   // 创建元素的文本节点
    para.appendChild(node); // 将文本节点添加到元素中 
     
    var p1 = document.getElementById("p1")
    var element = document.getElementById("div1");
    element.removeChild(p1)   // 移除元素节点
    element.appendChild(para);  // 将元素节点添加到元素中
    </script>
    
  • DOM 需要清楚您需要删除的元素,以及它的父元素,所以如果你只想要写要删除的元素,你可以这样:

    var child = document.getElementById("p1");
    child.parentNode.removeChild(child);  // 先得到父元素节点,再移除节点
    
  • 替换节点方法replaceChild(新节点,旧节点)

JavaScript高级

1、JavaScript对象
  • 在JavaScript中,所有事物都可以被包装为对象

  • Object 构造函数创建一个对象包装器,该参数从 Object.prototype 继承属性和方法

  • JavaScript 是面向对象的语言,但 JavaScript 不使用类。JavaScript 基于 prototype,而不是基于类的。

  • 当你尝试访问一个基本类型的属性或方法时,JavaScript 会自动临时地将这个基本类型的值转换为对应的包装对象,以便可以调用该对象上的属性和方法。这种转换是自动进行的,通常被称为**“装箱”**。一旦属性和方法的使用完毕,这个临时对象就会被销毁(拆箱),值又恢复为其原始的基本类型

    let str = "Hello";
    console.log(str.length); // 输出 5
    //在上面的代码中,str 是一个字符串基本类型的值。当我们尝试访问 str.length 时,JavaScript 会临时地将 str 转换为一个 String 对象,以便可以访问 length 属性。一旦 length 被获取,这个临时的 String 对象就会被销毁,str 仍然保持为字符串基本类型。
    
  • 频繁的装箱和拆箱可能会影响性能

2、JavaScript prototype
  • **原型(prototype)**为函数对象提供了继承和共享属性的机制

    • prototype是函数对象的内置属性,通过(_ _ proto _ _)访问
    • 作用是实现属性和方法的共享,从而减少内存的占用
    • 原型是一个对象,它是其他对象的模板或蓝图
    • 所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例
  • 对象通过**原型链(prototype chain)**来实现继承

    • 所有的 JavaScript 对象都会从另一个 prototype(原型对象)中继承属性和方法

    • 当一个对象试图访问一个属性或方法时,如果在该对象自身没有找到,JavaScript 会沿着原型链向上查找,直到找到对应的属性或方法,或者达到原型链的顶端 null 为止

      // 修改对象自己的原型,这样可以影响到所有基于该原型创建的对象
      Person.prototype.属性 = 属性值
      // 访问一个对象外面的原型
      console.log(Person.__proto__)  // 打印的是对象Person的原型对象
      
  • Object.create 方法

    • 该方法允许你创建一个新对象,并将其原型设置为指定的对象

      let Person = Object.create(Object)
      // 创建一个对象Person,设置其原型为Object
      
  • 利用prototype来使代码更加简洁:使用构造器(函数体)定义属性,使用原型对象(prototype)定义方法。

    如此,构造器只包含属性定义,而方法则分装在不同的代码块,使代码更具可读性

3、JavaScript Number 对象
  • 在JavaScript中,数字不分为整数类型和浮点型类型,所有的数字都是由 浮点型类型(64位浮点格式)

  • 最大值为(Number.MAX_VALUE),最小值为(Number.MIN_VALUE),无穷大为Infinity

  • 如果前缀为 0,则 JavaScript 会把数值常量解释为八进制数,如果前缀为 0 和 “x”,则解释为十六进制数

  • 可以使用 toString() 方法 输出16进制、8进制、2进制

    var myNumber=128;
    myNumber.toString(16);   // 返回 80
    myNumber.toString(8);    // 返回 200
    myNumber.toString(2);    // 返回 10000000
    
  • Number对象的常用方法

    • parseInt:将字符串转换为整数
    • parseFloat:将字符串转化为浮点数
    • isNaN:判断是否为NaN
    • toFixed:返回指定小数位数的表示形式
4、JavaScript String 对象
  • 字符串使用 indexOf() 来定位字符串中某一个指定的字符首次出现的位置,如没找到则返回-1

  • replace() 方法在字符串中用某些字符替换另一些字符,返回新的字符串

  • 字符串使用split()函数分割之后转为数组

  • Javascript 中可以使用反斜线(\)的转义功能插入特殊符号

  • 手写trim( )方法:

    if(typeof(String.prototype.trim) === "undefined") // 先判断有没有这个属性
    {
        String.prototype.trim = function()   // 把该方法写在String的原型上
        {
            return String(this).replace(/^\s+|\s+$/g, '');
        };
    }
    
5、JavaScript 对象系统的核心机制
  • prototype(原型)属性

    • 只有函数拥有该属性,就是说protptype是Function对象的一个属性
    • prototype是用于保存对象的共享属性和方法的,原型的属性和方法并不会影响函数本身的属性和方法
    • 当函数作为构造函数时,实例的_ _proto __ 会指向构造函数的prototype
  • _ _proto__属性

    • 所有对象都有_ _proto__属性

    • 用于构成原型链,实现继承

    • Object.getPrototypeOf(obj):获取obj的prototype

      const obj = {};
      console.log(obj.__proto__ === Object.prototype); // true
      console.log(Object.getPrototypeOf(obj)===Object.prototype) //true
      console.log(Object.getPrototypeOf(obj)===obj.__proto__)
      
  • constructor属性

    • 一个对象的prototype属性内保存着这个对象的共享属性和方法,里面有一个共享属性叫做constructor,该属性会指回该对象,如下:

      function Person() {}
      console.log(Person.prototype.constructor === Person); // true
      
  • 三者关系图

    实例对象
    {
    _ proto_: --------> 构造函数的 prototype 对象
    } {
    constructor: --> 构造函数本身
    _ _proto _ _: ----> 再往上一级的原型 (如 Object.prototype)
    }

    function Person(name) {
      this.name = name;
    }
    
    // 1. 构造函数默认会有 prototype 属性,指向内部
    console.log(Person.prototype); // { constructor: Person }
    
    // 2. 创建实例
    const john = new Person('John');
    
    // 3. 实例的 __proto__ 指向其构造函数的 prototype,即指向外部
    console.log(john.__proto__ === Person.prototype); // true
    
    // 4. 原型对象的 constructor 指回构造函数,即跳回自己本身
    console.log(Person.prototype.constructor === Person); // true
    
    // 5. 原型对象本身也是对象,也有 __proto__
    console.log(Person.prototype.__proto__ === Object.prototype); // true
    
    // 6. Object.prototype 是最顶层的原型
    console.log(Object.prototype.__proto__); // null
    

JavaScript BOM

1、JavaScript Window
  • BOM全称浏览器对象模型(Browser Object Model )

  • 所有浏览器都支持 window 对象。它表示浏览器窗口。所有 JavaScript 全局对象、函数以及变量均自动成为 window 对象的成员,甚至 HTML DOM 的 document 也是 window 对象的属性之一

    window.document.getElementById("header");
    
  • Window 尺寸

    var w=window.innerWidth
    || document.documentElement.clientWidth
    || document.body.clientWidth;
     
    var h=window.innerHeight
    || document.documentElement.clientHeight
    || document.body.clientHeight;
    // 使用||可以确保兼容不同的浏览器
    
  • window.open() - 打开新窗口
    window.close() - 关闭当前窗口
    window.moveTo() - 移动当前窗口
    window.resizeTo() - 调整当前窗口的尺寸

  • 全局变量不能通过 delete 操作符删除;而 window 属性上定义的变量可以通过 delete 删除

2、JavaScript Window Screen
  • window.screen 对象包含有关用户屏幕的信息
    • screen.availWidth - 可用的屏幕宽度
    • screen.availHeight - 可用的屏幕高度
3、JavaScript Window Location
  • window.location 对象用于获得当前页面的地址 (URL),并把浏览器重定向到新的页面
    • location.hostname 返回 web 主机的域名
    • location.pathname 返回当前页面的路径和文件名
    • location.port 返回 web 主机的端口 (80 或 443)
    • location.protocol 返回所使用的 web 协议(http: 或 https:)
    • location.href 返回当前页面的 URL
    • location.assign 加载 URL 指定的新的 HTML 文档
4、JavaScript Window history
  • window.history 对象包含浏览器的历史
    • history.back() 方法加载历史列表中的前一个 URL
    • history forward() 方法加载历史列表中的下一个 URL
5、JavaScript Window Navigator
  • window.navigator 对象包含有关访问者浏览器的信息

    <script>
    txt = "<p>浏览器代号: " + navigator.appCodeName + "</p>";
    txt+= "<p>浏览器名称: " + navigator.appName + "</p>";
    txt+= "<p>浏览器版本: " + navigator.appVersion + "</p>";
    txt+= "<p>启用Cookies: " + navigator.cookieEnabled + "</p>";
    txt+= "<p>硬件平台: " + navigator.platform + "</p>";
    txt+= "<p>用户代理: " + navigator.userAgent + "</p>";
    txt+= "<p>用户代理语言: " + navigator.language + "</p>";
    document.getElementById("example").innerHTML=txt;
    </script>
    
6、JavaScript 弹窗
  • window.alert:警告框
  • window.confirm:确认框,返回boolean
  • window.prompt:提示框,返回输入值
7、JavaScript 计时事件
  • window.setInterval:间隔指定的毫秒数不停地执行指定的代码
    • clearInterval() 方法用于停止 setInterval() 方法执行的函数代码
  • window.setTimeout:在指定的毫秒数后执行指定代码
    • clearTiemout()清理
8、JavaScript Cookie
  • Cookie 用于存储 web 页面的用户信息

  • 当浏览器从服务器上请求 web 页面时, 属于该页面的 cookie 会被添加到该请求中。服务端通过这种方式来获取用户的信息。

  • JavaScript 可以使用 document.cookie 属性来创建 、读取、及删除 cookie

    //Cookie 以名/值对形式存储
    username=John Doe
    
    //JavaScript 中,创建 cookie 如下所示:
    document.cookie="username=John Doe";
    
    //您还可以为 cookie 添加一个过期时间(以 UTC 或 GMT 时间)。默认情况下,cookie 在浏览器关闭时删除:
    document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT";
    
    //您可以使用 path 参数告诉浏览器 cookie 的路径。默认情况下,cookie 属于当前页面。
    document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值