JavaScript学习笔记

文章目录

一、JavaScript基础

JavaScript 是脚本语言。
所有现代的 HTML 页面都使用 JavaScript。

1.1 JavaScript 输出

JavaScript 可以通过不同的方式来输出数据:

  • 使用 window.alert() 弹出警告框。

    window.alert(5 + 6);
    
  • 使用 document.write() 方法将内容写到 HTML 文档中。

    document.write(Date());
    
  • 使用 innerHTML 写入到 HTML 元素。

    <p id="demo">我的第一个段落</p>
    
    <script>
    document.getElementById("demo").innerHTML = "段落已修改。";
    </script>
    
  • 使用 console.log() 写入到浏览器的控制台。

1.2. JavaScript 数据类型

JavaScript 有 7 种原始数据类型:

String(字符型)、 Number(数值型)、 Boolean(布尔值型)、Undefined、
Null、Object(对象型)、Symbol(符号型)

1.2.1 值类型/原始类型/基本类型

值类型在赋值操作时将变量的内容赋值给新的变量

  • undefined 未定义的值 。这个值的语义是,希望表示一个变量最原始的状态,而非人为操作的结果 。
  • null 空值 。这个值的语义是,希望表示 一个对象被人为的重置为空对象,而非一个变量最原始的状态 。 在内存里的表示就是,栈中的变量没有指向堆中的内存对象
  • Boolean
  • String
  • Number
  • Symbol 唯一的标识符,对象的属性键只能是字符串类型或者 Symbol 类型。

1.2.2 引用类型(对象)

引用类型在赋值操作时是将变量的指针赋值给新的变量,修改一个,另一个会一起改变

  • Object 对象类型
  • Array 数组类型

1.2.3 基本类型和引用类型的区别

不同的存储方式:

  • 基本类型:基本类型值在内存中占据固定大小,保存在栈内存中。
  • 引用类型:引用类型的值是对象,保存在堆内存中,而栈内存存储的是对象的变量标识符和对象在堆内存的存储地址。

不同的复制方式:

  • 基本类型:从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本,并将该副本复制给新变量。
  • 引用类型:从一个变量向另一个变量复制引用类型的值,复制的是指针,最终两个变量都指向同一个对象。

1.3 JavaScript 作用域

在 JavaScript 中, 作用域为可访问变量,对象,函数的集合。

1.3.1 JavaScript 局部作用域

变量在函数内声明,变量为局部作用域。
局部变量:只能在函数内部访问。

function myFunction() {
    var carName = "Volvo";
    // 函数内可调用 carName 变量
}

局部变量在函数开始执行时创建,函数执行完后局部变量会自动销毁。

1.3.2 JavaScript 全局变量

变量在函数外定义,即为全局变量。
全局变量有 全局作用域: 网页中所有脚本和函数均可使用。

var carName = " Volvo";
 
// 此处可调用 carName 变量
function myFunction() {
    // 函数内可调用 carName 变量
}

1.3.3 HTML 中的全局变量

在 HTML 中, 全局变量是 window 对象: 所有数据变量都属于 window 对象。

//此处可使用 window.carName
 
function myFunction() {
    carName = "Volvo";
}

1.3.4 块级作用域

ES6 中新增了块级作用域。块作用域由 { } 包括,if 语句和 for 语句里面的 { } 也属于块作用域。

ES6提供let变量实现块级作用域

function fxFn () { // 这是一个块级作用域
    let fx = 'fx is a great girl'
    if (true) { // 这是一个块级作用域
        let fx = 'fx is 18 years old'
    }
    console.log(fx) // fx is a great girl
}
fxFn()
// 块级作用域之间相互不影响

1.4 JavaScript 事件

HTML 元素中可以添加事件属性,使用 JavaScript 代码来添加 HTML 元素

<button onclick="getElementById('demo').innerHTML=Date()">现在的时间是?</button>
  • onchange HTML 元素改变
  • onclick 用户点击 HTML 元素
  • onmouseover 用户在一个HTML元素上移动鼠标
  • onmouseout 用户从一个HTML元素上移开鼠标
  • onkeydown 用户按下键盘按键
  • onload 浏览器已完成页面的加载

1.5 JavaScript 字符串

JavaScript 字符串用于存储和处理文本。

var carname = "Volvo XC60";

你可以使用索引位置来访问字符串中的每个字符:

var character = carname[7];

可以使用内置属性 length 来计算字符串的长度:

var sln = txt.length;

1.6 typeof与instanceof

1.6.1 typeof

使用 typeof 操作符来检测变量的数据类型。

typeof "John"                // 返回 string
typeof 3.14                  // 返回 number
typeof false                 // 返回 boolean
typeof [1,2,3,4]             // 返回 object
typeof {name:'John', age:34} // 返回 object

对于 Array,Null 等特殊对象使用 typeof 一律返回 object,这正是 typeof 的局限性。

1.6.2 instanceof

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

var a=new Array();
alert(a instanceof Array); // true

常用来判断某个实例对象的引用类型,不能用来判断基础类型

1.7 JavaScript 错误

  • try语句测试代码块的错误。

  • catch 语句处理错误。

  • throw 语句创建自定义错误。

  • finally语句在 try 和 catch 语句之后,无论是否有触发异常,该语句都会执行。

try { 
    if(x == "") throw "值是空的";
    if(isNaN(x)) throw "值不是一个数字";
    x = Number(x);
    if(x > 10) throw "太大";
    if(x < 5) throw "太小";
  }
  catch(err) {
    message.innerHTML = "错误: " + err + ".";
  }
  finally {
    document.getElementById("demo").value = "";
  }

throw 语句允许我们创建自定义错误。catch 块会捕捉到 try 块中的错误,并执行代码来处理它。finally 语句不论之前的 try 和 catch 中是否产生异常都会执行该代码块

1.8 JavaScript 变量提升

  • JavaScript 中,函数及变量的声明都将被提升到函数的最顶部。
  • JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。
  • JavaScript 只有声明的变量会提升,初始化的不会。

1.9 JavaScript 函数定义

JavaScript 使用关键字 function 定义函数。

函数声明后不会立即执行,会在我们需要的时候调用到。

function myFunction(a, b) {
    return a * b;
}

1.9.1 函数提升

提升(Hoisting)是 JavaScript 默认将当前作用域提升到前面去的的行为

myFunction(5);

function myFunction(y) {
    return y * y;
}

1.9.2 自调用函数

如果表达式后面紧跟 () ,则会自动调用。
通过添加括号,来说明它是一个函数表达式:

(function () {
    var x = "Hello!!";      // 我将调用自己
})();

1.9.3 闭包

闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。

function demo(){
	let i = 1;
	return function sum(){
		i++;
		console.log(i);
	}
}

简单来说就是函数嵌套函数,内部函数可以引用来外部函数的变量,因为外部函数变量一直在被引用,所以不会被释放

直观的说就是形成一个不销毁的栈环境。

1.9.3.1 闭包的作用

它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中

1.9.3.2 闭包实际场景应用—函数防抖

比如要缩放窗口 触发onresize 事件 需要在这时候做一件事情,但是我们希望拖动的时候只触发一次,

window.onresize = debounce(fn,500)

function debounce(fn,wait){
        var timer = null
        var check = 1;
        return function(){
  			check++
	        if(timer){     //timer第一次执行后会保存在内存里 永远都是执行器 直到最后被触发
	           clearTimeout(timer)
	            timer = null
	        }
	        timer = setTimeout(()=>fn(),wait)
        }
}

var fn = function(){
    console.log('fn')
} 
1.9.3.3 闭包实际场景应用—单例模式
class CreateUser {
    constructor(name) {
        this.name = name;
        this.getName();
    }
    getName() {
         return this.name;
    }
}
// 代理实现单例模式
var ProxyMode = (function() {
    var instance = null;
    return function(name) {
        if(!instance) {
            instance = new CreateUser(name);
        }
        return instance;
    }
})();
// 测试单体模式的实例
var a = ProxyMode("aaa");
var b = ProxyMode("bbb");
// 因为单体模式是只实例化一次,所以下面的实例是相等的
console.log(a === b);    //true
1.9.3.4 闭包实际场景应用—单例模式
class CreateUser {
    constructor(name) {
        this.name = name;
        this.getName();
    }
    getName() {
         return this.name;
    }
}
// 代理实现单例模式
var ProxyMode = (function() {
    var instance = null;
    return function(name) {
        if(!instance) {
            instance = new CreateUser(name);
        }
        return instance;
    }
})();
// 测试单体模式的实例
var a = ProxyMode("aaa");
var b = ProxyMode("bbb");
// 因为单体模式是只实例化一次,所以下面的实例是相等的
console.log(a === b);    //true
1.9.3.5 setTimeout输出正确的值
for(var i=0;i<10;i++){
((j)=>{
  setTimeout(function(){
        console.log(j)//1-10
    },1000)})(i)
}
1.9.3.6 闭包产生内存泄漏

闭包会产生内存泄漏

使用了闭包容易形成“循环引用”。比如闭包的作用域链中保存着一些DOM节点,循环引用的两个对象都不会被基“引用计数的垃圾回收机制”回收内存。所以其根本原因是对象的“循环引用”导致的内存泄漏

1.9.4 高阶函数(HOF)

高阶函数是至少满足如下条件之一的函数:

  • 函数可以作为参数被传递
  • 函数可以作为返回值输出

在JavaScript中常见于回调函数则是作为了参数被传递,闭包则是返回了函数

1.9.4.1 高阶函数例子—单例模式

例如一个单例模式的例子,既将函数作为参数,也将函数作为返回值:

const getSingleBuider = function(fn) {
    let instance;
    return function() {
        return instance || (instance = fn.apply(this, arguments));
    }
}

1.9.5 函数的柯里化

通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式

function sum(a) {
    return function(b) {
        return function(c) {
            return a + b + c;
        }
    }
}
sum(1)(2)(3);  // output: 6

1.9.6 原型和原型链

1.9.6.1 prototype 原型对象

1.每个函数对象(构造函数)都有一个prototype 属性,这个属性指向函数的原型对象

2.在 JavaScript 中,每当定义一个对象(函数也是对象)时候,对象中都会包含一些预定义的属性(原型)。

3.原型对象包含特定类型的所有实例共享的属性和方法,即这个原型对象是用来给实例共享属性和方法的

function Person() {}
Person.prototype.name = 'Zaxlct';
Person.prototype.age  = 28;
Person.prototype.job  = 'Software Engineer';
Person.prototype.sayName = function() {
  alert(this.name);
}

var person1 = new Person();
person1.sayName(); // 'Zaxlct'

var person2 = new Person();
person2.sayName(); // 'Zaxlct'

console.log(person1.sayName == person2.sayName); //true

原型对象(Person.prototype)是 构造函数(Person)的一个实例。

1.9.6.2 constructor 构造函数

原型对象中的属性,指向该原型对象的构造函数

function Person(name, age, job) {
 this.name = name;
 this.age = age;
 this.job = job;
 this.sayName = function() { alert(this.name) } 
}
var person1 = new Person('Zaxlct', 28, 'Software Engineer');
var person2 = new Person('Mick', 23, 'Doctor');

上面的例子中 person1 和 person2 都是 Person 的实例。这两个实例都有一个 constructor (构造函数)属性,该属性(是一个指针)指向 Person。

1.9.6.3 proto

实例中的属性,指向new这个实例的构造函数的原型对象

所有对象都有__proto__,但只有函数对象有prototype

在这里插入图片描述

1.9.6.4 原型链

在定义构造函数的prototype属性的时候,直接吧一个对象赋值给prototype。

每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。

当实例化对象调用某个方法时会先在自身和原型上查找,然后是在_proto_上一层层查找,这种方式就是原型链。

原型链呢,很像过去家谱的概念,可以从你往上追溯你父亲,到爷爷,到太爷爷一直到头,这就形成了一个链条,如果其中每个人都比作一个对象,那么这个链条就是原型链。

在这里插入图片描述

1.9.6.5 var p1 = new Person() 发生了什么
1.var p1 = new Object(); //此时p1._proto_ = Object Prototype
2.p1._proto_ = Person.prototype;
3.Person.call(p1);//使用新对象p1调用函数Person,将this作用域给p1
1.9.6.5 继承

1.组合继承:结合 原型链+借用构造函数 方式,实现组合继承。

//Super中定义属性name
function Super(name){
    this.name = name;
    this.color = ['red','green'];
}
//Super的原型中定义方法
Super.prototype.sayname = function(){
    console.log(this.name);
}
function Sub(name, age){
    //通过构造函数的方式继承Super的属性
    Super.call(this, name);
    //定义自己的属性
    this.age = age;
}
//通过原型链的方式继承方法
Sub.prototype = new Super();
Sub.prototype.constructor = Sub;

var ins1 = new Sub('ins1',18);

//缺点:会调用两次超类的构造函数,一次在Super.call(this, name); 一次在Sub.prototype = new Super();
//导致Sub原型上有属性name、age,Sub实例上也有属性name、age。

2.原型式继承:借助原型,基于已有的对象创建新对象。

// object.Create(参数1,参数2); 
// 参数1用作新对象的原型对象,
// 参数2为新对象定义额外属性的对象。
var person = {
    name: 'person'
}
//基于已有的person对象,创建一个新的anthorp对象
var anthorp = Object.create(person);
//相当于如下语句
function object(o){
    function F(){};
    F.prototype = o;
    return new F();
}
//得到一个以person为原型的构造函数的实例
var anthorp = object(person);

二、JavaScript 对象

对象只是一种特殊的数据。对象拥有属性和方法。

2.1 Date 对象

Date 对象用于处理日期与时间。

可以通过 new 关键词来定义 Date 对象。

new Date();
new Date(value);
new Date(dateString);
new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]]);

2.1.1 Date对象的方法

  • getFullYear()
    使用 getFullYear() 获取年份。

  • getTime()
    getTime() 返回从 1970 年 1 月 1 日至今的毫秒数。

  • setFullYear()
    如何使用 setFullYear() 设置具体的日期。

  • toUTCString()
    如何使用 toUTCString() 将当日的日期(根据 UTC)转换为字符串。

  • getDay()
    如何使用 getDay() 和数组来显示星期,而不仅仅是数字。

2.2 Math 对象

Math 对象用于执行数学任务。

Math 对象并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math()。

JavaScript Math 对象的参考手册

2.2.1 random() 方法

返回介于 0(包含) ~ 1(不包含) 之间的一个随机数:

Math.random()
// Math.floor()向下取整
Math.floor((Math.random()*100)+1);

2.4 Array 对象

Array 对象用于在变量中存储多个值:

var cars = ["Saab", "Volvo", "BMW"];

2.4.1 length 属性

设置或返回数组元素的个数。

2.4.2 toString() 方法

数组中 toString() 方法能够把每个元素转换为字符串,然后以逗号连接输出显示。

var a = [1,2,3,4,5,6,7,8,9,0];  //定义数组
var s = a.toString();  //把数组转换为字符串
console.log(s);  //返回字符串“1,2,3,4,5,6,7,8,9,0”

2.4.3 join() 方法

join() 方法可以把数组转换为字符串,不过它可以指定分隔符。
不指定分隔符时与 toString()相同。

var a = [1,2,3,4,5];  //定义数组
var s = a.join("==");  //指定分隔符
console.log(s);  //返回字符串“1==2==3==4==5”

2.4.4 sort() 方法

sort() 函数默认将数组元素升序排列,该函数并不是按照数字递增的方式排列的,而是按照元素的 ASCII 码或者 Unicode 码进行排序

sort()可以接受一个比值函数,使数字从小到大排序

sort(function(a, b){return a-b})

对数组中的对象进行排序:

return array.sort(function (a, b) {
            let x = a[key];
            let y = b[key];
            return ((x < y) ? -1 : (x > y) ? 1 : 0)
          })

2.4.5 pop() 方法

pop() 方法从数组中删除最后一个元素

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.pop();              // 从 fruits 删除最后一个元素("Mango")
//pop() 方法返回“被弹出”的值:
var x = fruits.pop();      // x 的值是 "Mango"

2.4.6 push() 方法

push() 方法(在数组结尾处)向数组添加一个新的元素

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.push("Kiwi");       //  向 fruits 添加一个新元素
//push() 方法返回新数组的长度:
var x =  fruits.push("Kiwi");   //  x 的值是 5

2.4.7 shift() 方法

shift() 方法会删除首个数组元素,并把所有其他元素“位移”到更低的索引。
shift() 方法会返回删除的元素

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.shift();             
// 返回 "Banana"
// 从 fruits 删除第一个元素 "Banana"

2.4.8 unshift() 方法

unshift() 方法(在开头)向数组添加新元素,并“反向位移”旧元素
unshift() 方法返回新数组的长度。

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.unshift("Lemon");    // 向 fruits 添加新元素 "Lemon",返回 5

2.4.9 slice() 方法

slice()方法可提取数组的某个部分,并以新的数组返回被提取的部分。

var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
var citrus = fruits.slice(1,3);

2.4.10 splice() 方法

splice() 方法用于添加或删除数组中的元素。

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2, 0, "Lemon", "Kiwi");

第一个参数(2)定义了应添加新元素的位置(拼接)。

第二个参数(0)定义应删除多少元素。

其余参数(“Lemon”,“Kiwi”)定义要添加的新元素。

splice() 方法返回一个包含已删除项的数组。

2.4.11 forEach() 方法

forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。。
forEach() 方法没有返回值,会修改原数组

var txt = "";
var numbers = [45, 4, 9, 16, 25];
numbers.forEach(myFunction);

function myFunction(value, index, array) {
  txt = txt + value + "<br>"; 
}

2.4.12 map() 方法

map() 方法通过对每个数组元素执行函数来创建新数组。

map() 不会改变原始数组。

map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。

var numbers1 = [45, 4, 9, 16, 25];
var numbers2 = numbers1.map(myFunction);

function myFunction(value) {
  return value * 2;
}

2.4.13 filter() 方法

filter() 方法创建一个包含通过测试的数组元素的新数组。

这个例子用值大于 18 的元素创建一个新数组:

var numbers = [45, 4, 9, 16, 25];
var over18 = numbers.filter(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}

2.4.14 reduce() 方法

reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。

reduce() 方法在数组中从左到右工作。。

reduce() 方法不会减少原始数组。

这个例子确定数组中所有数字的总和:

var numbers1 = [45, 4, 9, 16, 25];
var sum = numbers1.reduce(myFunction);

function myFunction(total, value, index, array) {
  return total + value;
}

2.4.15 every() 方法

every() 方法检查所有数组值是否通过测试。如果所有元素都通过检测返回 true,否则返回 false。

这个例子检查所有数组值是否大于 18:

var numbers = [45, 4, 9, 16, 25];
var allOver18 = numbers.every(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}

2.4.16 some() 方法

some() 方法检查某些数组值是否通过了测试。如果数组中有元素满足条件返回 true,否则返回 false。

这个例子检查某些数组值是否大于 18:

var numbers = [45, 4, 9, 16, 25];
var someOver18 = numbers.some(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}

2.4.16 indexOf() 方法

indexOf() 方法在数组中从左往右搜索元素值并返回其位置。不存在返回-1。

var fruits = ["Apple", "Orange", "Apple", "Mango"];
var a = fruits.indexOf("Apple");  // 2

2.4.17 lastIndexOf() 方法

lastIndexOf() 方法在数组中从右往左搜索元素值并返回其位置。不存在返回-1。

var fruits = ["Banana", "Orange", "Apple", "Mango"];
var a = fruits.lastIndexOf("Apple"); // 2

2.4.18 find() 方法

find() 方法返回通过测试函数的第一个数组元素的值。

这个例子查找(返回)大于 18 的第一个元素的值:

var numbers = [4, 9, 16, 25, 29];
var first = numbers.find(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}

2.4.19 findIndex() 方法

findIndex() 方法返回通过测试函数的第一个数组元素的索引。

这个例子查找大于 18 的第一个元素的索引:

var numbers = [4, 9, 16, 25, 29];
var first = numbers.findIndex(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}

2.4.20 includes() 方法

includes() 方法用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false。

[1, 2, 3].includes(2);     // true
[1, 2, 3].includes(4);     // false

2.3 String 对象

String 对象用于处理文本(字符串)

var txt = new String("string");
或者更简单方式:
var txt = "string";

2.3.1 split() 方法

split() 方法用于把一个字符串分割成字符串数组。

该方法可以指定两个参数,第 1 个参数为分隔符,指定从哪儿进行分隔的标记;第 2 个参数指定要返回数组的长度。

var s = "1==2== 3==4 ==5";
var a = s.split("==");
console.log(a); //[1,2,3,4,5]
console.log(a.constructor == Array);

2.3.1 charAt() 方法

charAt(x)返回字符串中x位置的字符,下标从 0 开始。

2.3.2 concat() 方法

concat() 方法用于连接两个或多个字符串,此方法不改变现有的字符串,返回拼接后的新的字符串。

//concat(v1, v2,..)
var message="Sam"
var final=message.concat(" is a"," hopeless romantic.")
//alerts "Sam is a hopeless romantic."
alert(final)

2.3.3 indexOf() 方法

indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。

如果没有找到匹配的字符串则返回 -1。

var str="Hello world, welcome to the universe.";
var n=str.indexOf("welcome");  // 13

2.3.4 lastIndexOf() 方法

lastIndexOf() 方法返回指定文本在字符串中最后一次出现的索引

如果未找到,则返回-1。

var str="I am from runoob,welcome to runoob site.";
var n=str.lastIndexOf("runoob"); // 28

2.3.5 match(regexp) 方法

根据正则表达式在字符串中搜索匹配项。如果没有找到匹配项,则返回null。

var str="The rain in SPAIN stays mainly in the plain"; 
var n=str.match(/ain/g); // ain,ain,ain

这个方法的行为在很大程度上有赖于 regexp 是否具有标志 g。如果 regexp 没有标志 g,那么 match() 方法就只能在 stringObject 中执行一次匹配。

2.3.6 replace() 方法

replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。

默认只执行一次替换

var str="Visit Microsoft! Visit Microsoft!";
var n=str.replace("Microsoft","Runoob");  // Visit Runoob!Visit Microsoft!

执行全部替换需要/g

var str="Visit Microsoft! Visit Microsoft!";
var n=str.replace(/Microsoft/g,"Runoob");  // Visit Runoob!Visit Runoob!

2.3.7 search() 方法

search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串

如果找到,返回与 regexp 相匹配的子串的起始位置,否则返回 -1。

//search(regexp)
var intRegex = /[0-9 -()+]+$/;
 
var myNumber = '999';
var isInt = myNumber.search(intRegex);
console.log(isInt);
//output: 0

2.3.8 slice() 方法

slice() 方法可提取字符串的某个部分,返回一个新的字符串。

包括字符串从 start 开始(包括 start)到 end 结束(不包括 end)为止的所有字符。

var text="excellent"
text.slice(0,4) //returns "exce"
text.slice(2,4) //returns "ce"

2.3.9 substr() 方法

substr() 方法可在字符串中抽取从 start 下标开始的指定数目的字符。返回一个新的字符串,包含从 start(包括 start 所指的字符) 处开始的 length 个字符。

如果没有指定 length,那么返回的字符串包含从 start 到该字符串的结尾的字符。

var text="excellent"
text.substring(0,4) //returns "exce"
text.substring(2,4) //returns "cell"

2.3.10 substring(from, [to]) 方法

substring() 方法用于提取字符串中介于两个指定下标之间的字符,返回的子串包括 start 处的字符,但不包括 to处的字符

如果省略to参数,那么返回的子串会一直到字符串的结尾。

var myString = 'javascript rox';
myString = myString.substring(0,10);
console.log(myString) // javascript

2.3.11 toLowerCase() 方法

toLowerCase() 方法用于把字符串转换为小写。

var myString = 'JAVASCRIPT ROX';
myString = myString.toLowerCase();
console.log(myString) // javascript rox

2.3.12 toUpperCase() 方法

toUpperCase() 方法用于把字符串转换为大写。

var myString = 'javascript rox';
myString = myString.toUpperCase();
console.log(myString) //output: JAVASCRIPT ROX

2.3.13 trim() 方法

trim() 方法会从一个字符串的两端删除空白字符。

在这个上下文中的空白字符是所有的空白字符 (space, tab, no-break space 等) 以及所有行终止符字符(如 LF,CR)

var str = "     Hello Edureka!     ";
alert(str.trim());   // Hello Edureka!

2.3.14 test() 方法

test() 方法用于检测一个字符串是否匹配某个模式.

如果字符串中有匹配的值返回 true ,否则返回 false。

常用于正则表达式校验

if ((/^1\d{0,10}$/.test(userName))) {
...
}

2.4 JSON 对象

2.4.1 JSON.stringify() 方法

用于将 JavaScript 值转换为 JSON 字符串。

let obj = {
  name: 'fmk',
  age: 22,
  friend: {
    name: 'wh',
    age: 21
  }
};

let copyObj31 = JSON.stringify(obj);
<!--"{"name":"fmk","age":22,"friend":{"name":"wh","age":21}}"-->

2.4.2 JSON.parse() 方法

用于将一个 JSON 字符串转换为 JavaScript 对象。

let obj = {
  name: 'fmk',
  age: 22,
  friend: {
    name: 'wh',
    age: 21
  }
};

let copyObj = JSON.stringify(obj);
<!--"{"name":"fmk","age":22,"friend":{"name":"wh","age":21}}"-->
let copyObj2 = JSON.parse(copyObj31);
<!--Object
name: "fmk"
age: 22
friend: {name: "wh", age: 21}
__proto__: Object-->

JSON.parse() 和 JSON.stringify()一起使用常用作深拷贝,创建一个新的对象,且与obj对象完全一样:

let copyObj3 = JSON.parse(JSON.stringify(obj));

三、call() apply() bind() 的用法

3.1 call() 方法

call() 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法。

当调用一个函数时,可以赋值一个不同的 this 对象。this 引用当前对象,即 call 方法的第一个参数。

通过 call 方法,你可以在一个对象上借用另一个对象上的方法,比如Object.prototype.toString.call([]),就是一个Array对象借用了Object对象上的方法。

var name = 123;
function b(name) {
	console.log(this.name+name);
}
	const obj = {name:"obj你好"};
	// 当调用b 方法的时候,该方法的 this 值会绑定到obj对象。
	b.call(obj);  //obj你好undefined
	b.call();     //123undefined
	b.call(obj,"fmk"); //obj你好fmk

3.2 apply() 方法

语法与 call() 方法的语法几乎完全相同,唯一的区别在于,apply的第二个参数必须是一个包含多个参数的数组

function jsy(x,y,z){
    console.log(x,y,z);
}

jsy.apply(null,[1,2,3]); 
// 1 2 3

apply 的所有参数都必须放在一个数组里面传进去

3.3 bind() 方法

bind 除了返回是函数以外,它 的参数和 call 一样

  • 不会执行对应的函数,call或apply会自动执行对应的函数
  • 返回对函数的引用

以下运行结果一样

obj.myFun.call(db,'成都','上海');     // 德玛 年龄 99  来自 成都去往上海
obj.myFun.apply(db,['成都','上海']);      // 德玛 年龄 99  来自 成都去往上海  
obj.myFun.bind(db,'成都','上海')();       // 德玛 年龄 99  来自 成都去往上海

以下示例通过binddocument添加click事件监听,并绑定EventClick函数

var obj = {name:'JSLite.io'};
/**
 * 给document添加click事件监听,并绑定EventClick函数
 * 通过bind方法设置EventClick的this为obj,并传递参数p1,p2
 */
document.addEventListener('click',EventClick.bind(obj,'p1','p2'),false);
//当点击网页时触发并执行
function EventClick(a,b){
    console.log(
            this.name, //JSLite.io
            a, //p1
            b  //p2
    )
}
// JSLite.io p1 p2

四、HTML DOM

通过 HTML DOM,可访问 JavaScript HTML 文档的所有元素。

当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。

HTML DOM 模型被构造为对象的树:
在这里插入图片描述
通过可编程的对象模型,JavaScript 获得了足够的能力来创建动态的 HTML。

4.1 查找 HTML 元素

通常,通过 JavaScript,您需要操作 HTML 元素。

4.1.1 通过 id 查找 HTML 元素

在 DOM 中查找 HTML 元素的最简单的方法,是通过使用元素的 id。

x=document.getElementById("intro");

4.1.2 通过标签名查找 HTML 元素

本例查找 id=“main” 的元素,然后查找 id=“main” 元素中的所有 <p> 元素:

var x=document.getElementById("main");
var y=x.getElementsByTagName("p");

查找结果为 HTMLCollection 对象

4.1.3 通过类名找到 HTML 元素

本例通过 getElementsByClassName 函数来查找 class=“intro” 的元素:

var x=document.getElementsByClassName("intro");

查找结果为 HTMLCollection 对象

4.2 改变 HTML

4.2.1 改变 HTML 输出流

在 JavaScript 中,document.write() 可用于直接向 HTML 输出流写内容。

document.write(Date());

4.2.2 改变 HTML 内容

修改 HTML 内容的最简单的方法是使用 innerHTML 属性。

document.getElementById("p1").innerHTML="新文本!";

4.2.3 改变 HTML 属性

如需改变 HTML 元素的属性,请使用这个语法:

// attribute表示需要改变的属性
document.getElementById(id).attribute=新属性值
document.getElementById(id).setAttribute("属性键","属性值");

例子:

<img id="image" src="smiley.gif">

<script>
document.getElementById("image").src="landscape.jpg";
// 等同于
document.getElementById("image").setAttribute("src","landscape.jpg");
</script>
在这里插入代码片

4.3 改变CSS

HTML DOM 允许 JavaScript 改变 HTML 元素的样式。

4.3.1 改变 HTML 样式

如需改变 HTML 元素的样式,请使用这个语法:

document.getElementById(id).style.property=新样式

例子:

document.getElementById("p2").style.color="blue";
document.getElementById("p2").style.fontFamily="Arial";
document.getElementById("p2").style.fontSize="larger";

4.3.2 classList.add() 添加class

实现dom元素添加class

let maodianList = document.getElementById(`list`);

// 添加class
maodianList.classList.add('active');

// 删除class
maodianList.classList.remove('active');

4.3.3 setAttribute() 修改dom属性

document.getElementById("p").setAttribute("class", "para-tree");

4.4 DOM 事件

HTML DOM 使 JavaScript 有能力对 HTML 事件做出反应。

4.4.1 HTML 事件属性

如需向 HTML 元素分配 事件,您可以使用事件属性。

// 向 button 元素分配 onclick 事件:
<button onclick="displayDate()">点这里</button>

4.4.2 使用 HTML DOM 来分配事件

HTML DOM 允许您使用 JavaScript 来向 HTML 元素分配事件:

// 向 button 元素分配 onclick 事件:
document.getElementById("myBtn").onclick=function(){displayDate()};

4.4.3 onload 和 onunload 事件

onload 和 onunload 事件会在用户进入或离开页面时被触发。

<body onload="checkCookies()">

4.4.4 onchange 事件

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

<input type="text" id="fname" onchange="upperCase()">

4.4.5 onmouseover 和 onmouseout 事件

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

<div onmouseover="mOver(this)" onmouseout="mOut(this)" style="background-color:#D94A38;width:120px;height:20px;padding:40px;">Mouse Over Me</div>
<script>
function mOver(obj){
	obj.innerHTML="Thank You"
}
function mOut(obj){
	obj.innerHTML="Mouse Over Me"
}
</script>

4.4.6 onmousedown、onmouseup 以及 onclick 事件

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

  • 首先当点击鼠标按钮时,会触发 onmousedown 事件,
  • 当释放鼠标按钮时,会触发 onmouseup 事件,
  • 最后,当完成鼠标点击时,会触发 onclick 事件。

4.4.7 onresize 事件

onresize 事件会在窗口或框架被调整大小时发生。

<body onresize="myFunction()">

4.5 HTML DOM EventListener

4.5.1 addEventListener() 方法

addEventListener() 方法用于向指定元素添加事件句柄。

addEventListener() 方法添加的事件句柄不会覆盖已存在的事件句柄。

addEventListener() 方法可以更简单的控制事件(冒泡与捕获)。

使用 addEventListener() 方法时, JavaScript 从 HTML 标记中分离开来,可读性更强

可以使用 removeEventListener() 方法来移除事件的监听。

element.addEventListener(event, function, useCapture);
  • 第一个参数是事件的类型 (如 “click” 或 “mousedown”).

  • 第二个参数是事件触发后调用的函数。

  • 第三个参数是个布尔值用于描述事件是冒泡还是捕获。该参数是可选的。
    注意:不要使用 “on” 前缀。 例如,使用 “click” ,而不是使用 “onclick”。

允许向同一个元素添加多个事件,且不会覆盖已存在的事件,可以向同个元素添加不同类型的事件:

element.addEventListener("mouseover", myFunction);
element.addEventListener("click", myFunction);
element.addEventListener("click", mySecondFunction);
element.addEventListener("mouseout", myThirdFunction);

向 Window 对象添加事件句柄,当用户重置窗口大小时添加事件监听:

window.addEventListener("resize", function(){
    document.getElementById("demo").innerHTML = sometext;
});

4.5.2 removeEventListener() 方法

removeEventListener() 方法移除由 addEventListener() 方法添加的事件句柄:

element.removeEventListener("mousemove", myFunction);

4.5.3 事件冒泡或事件捕获

事件传递有两种方式:冒泡与捕获。

冒泡 中,内部元素的事件会先被触发,然后再触发外部元素,即: <p> 元素的点击事件先触发,然后会触发 <div> 元素的点击事件。

捕获 中,外部元素的事件会先被触发,然后才会触发内部元素的事件,即: <div> 元素的点击事件先触发 ,然后再触发 <p> 元素的点击事件。

addEventListener() 方法可以指定 “useCapture” 参数来设置传递类型:

// 语法
addEventListener(event, function, useCapture);
// 示例
document.getElementById("myDiv").addEventListener("click", myFunction, true);

默认值为 false, 即冒泡传递,当值为 true 时, 事件使用捕获传递。

4.5.4 stopPropagation()

该函数只阻止事件向祖辈元素的传播,不会阻止该元素自身绑定的其他事件处理函数的函数。

document.getElementById("mybutton").οnclick=function(event)
 {
    alert('body click');
 	event.stopPropagation();//阻止了事件的向上传播
}

4.5.5 preventDefault()

该方法将通知 Web 浏览器不要执行与事件关联的默认动作(如果存在这样的动作)。

比如a标签点击会跳转的默认事件可以通过此方式取消。

event.preventDefault()

4.6 HTML DOM 元素 (节点)

4.6.1 createElement() 方法

用于创建 DOM 元素:

var para = document.createElement("p");

4.6.2 appendChild() 方法

在已存在的元素中添加新的元素。用于添加新元素到尾部。

para.appendChild(node);

4.6.3 insertBefore() 方法

在已存在的元素中添加新的元素。将新元素添加到另一个元素之前。

<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 element = document.getElementById("div1");
var child = document.getElementById("p2");
element.insertBefore(para, child);
</script>

4.6.4 removeChild() 方法

要移除一个元素,你需要知道该元素的父元素。

<div id="div1">
<p id="p1">这是一个段落。</p>
<p id="p2">这是另外一个段落。</p>
</div>
 
<script>
var parent = document.getElementById("div1");
var child = document.getElementById("p1");
parent.removeChild(child);
</script>

4.6.5 replaceChild() 方法

使用 replaceChild() 方法来替换 HTML DOM 中的元素

<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 parent = document.getElementById("div1");
var child = document.getElementById("p1");
parent.replaceChild(para, child);
</script>

4.7 HTML DOM 集合(Collection)

4.7.1 HTMLCollection 对象

HTMLCollection 对象类似包含 HTML 元素的一个数组。

getElementsByTagName() 方法返回 HTMLCollection 对象。

以下代码获取文档所有的 <p> 元素:

var x = document.getElementsByTagName("p");
// 访问第二个 <p> 元素可以是以下代码:
y = x[1];

HTMLCollection 对象的 length 属性定义了集合中元素的数量。

var myCollection = document.getElementsByTagName("p");
document.getElementById("demo").innerHTML = myCollection.length;

集合 length 属性常用于遍历集合中的元素。

// 修改所有 <p> 元素的背景颜色:
var myCollection = document.getElementsByTagName("p");
var i;
for (i = 0; i < myCollection.length; i++) {
    myCollection[i].style.backgroundColor = "red";
}

4.8 HTML DOM 节点列表

NodeList 对象是一个从文档中获取的节点列表 (集合) 。

NodeList 对象类似 HTMLCollection 对象。

一些旧版本浏览器中的方法(如:getElementsByClassName())返回的是 NodeList 对象,而不是 HTMLCollection 对象。

4.9 其他 DOM 方法

4.9.1 scrollIntoView() 方法

scrollIntoView只接受一个参数,但接受两种类型的参数,分别是Boolean型参数和Object型参数

  1. 先说Boolean型参数,如果为true,元素的顶端将和其所在滚动区的可视区域的顶端对齐。若为false,元素的底端将和其所在滚动区的可视区域的底端对齐。
  2. 之后是Object型参数,block参数start和end,与Boolean型的true和false一致。另一个选项是behavior,参数分别是auto、instant与smooth,决定页面是如何滚动的,auto与instant都是瞬间跳到相应的位置,而smooth就是有动画的过程
let obj = document.getElementById(id);
        if (obj) {
            obj.scrollIntoView({block: 'start', behavior: 'smooth'});
        }
4.9.1.1 实际运用:锚点定位

1.首先定义锚点id

<div className="api-manage-detail api-manage-maodian" key={v1.id} id={v1.id}>

2.编写滚动事件 获取dom的id然后scrollIntoView滚动

    const naver = (id: string) => () => {
        let obj = document.getElementById(id);
        if (obj) {
            obj.scrollIntoView({block: 'start', behavior: 'smooth'});
        }
        return false;
    };

4.监听滚动事件

    useEffect(() => {
        // 添加scroll事件的监听器
        window.addEventListener('scroll', throttle(() => {
            isShowTop();
        }, 50));
        return () => {
            window.removeEventListener('scroll', throttle(() => {
                isShowTop()
            }, 50));
        }
    }, []);

5.判断当前滚动的位置

    const isShowTop = () => {
        let scrollTop = document.documentElement.scrollTop;
        let maodianList = document.getElementById(`list`);
        if (scrollTop <= maodianList.offsetTop + maodianList.offsetHeight - 20) {
        
            
        }
    };

4.9.2 execCommand() 方法

execCommand() 方法执行浏览器复制命令

复制指定参数的函数

const copy = (row: string) => () => {
        const oInput = document.createElement('input');
        oInput.value = row;
        document.body.appendChild(oInput);
        oInput.select(); // 选择对象
        document.execCommand('Copy'); // 执行浏览器复制命令
        oInput.className = 'oInput';
        oInput.style.display = 'none';
        message.success('复制成功!');
    };

五、Window - 浏览器对象模型

浏览器对象模型 (BOM) 使 JavaScript 有能力与浏览器"对话"。

5.1 Window 对象

所有浏览器都支持 window 对象。它表示浏览器窗口。

所有 JavaScript 全局对象、函数以及变量均自动成为 window 对象的成员。

全局变量是 window 对象的属性。

全局函数是 window 对象的方法。

甚至 HTML DOM 的 document 也是 window 对象的属性之一:

window.document.getElementById("header");
// 与此相同:
document.getElementById("header");

5.2 Window 尺寸

有三种方法能够确定浏览器窗口的尺寸。

对于Internet Explorer、Chrome、Firefox、Opera 以及 Safari:

  • window.innerHeight - 浏览器窗口的内部高度(包括滚动条)
  • window.innerWidth - 浏览器窗口的内部宽度(包括滚动条)

对于 Internet Explorer 8、7、6、5:

  • document.documentElement.clientHeight
  • document.documentElement.clientWidth

或者

  • document.body.clientHeight
  • document.body.clientWidth

实用的 JavaScript 方案(涵盖所有浏览器):

var w=window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;

var h=window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;

5.3 Window Screen

window.screen 对象包含有关用户屏幕的信息。

window.screen对象在编写时可以不使用 window 这个前缀。

5.3.1 Window Screen 可用宽度

screen.availWidth 属性返回访问者屏幕的宽度,以像素计,减去界面特性,比如窗口任务栏。

<script>
document.write("可用宽度: " + screen.availWidth);
</script>

5.3.2 Window Screen 可用高度

screen.availHeight 属性返回访问者屏幕的高度,以像素计,减去界面特性,比如窗口任务栏。

<script>
document.write("可用高度: " + screen.availHeight);
</script>

5.4 Window Location

window.location 对象用于获得当前页面的地址 (URL),并把浏览器重定向到新的页面。

window.location 对象在编写时可不使用 window 这个前缀。

一些实例:

  • location.hostname 返回 web 主机的域名
  • location.pathname 返回当前页面的路径和文件名
  • location.port 返回 web 主机的端口 (80 或 443)
  • location.protocol 返回所使用的 web 协议(http: 或 https:)

5.4.1 Window Location Href

location.href 属性返回当前页面的 URL。

document.write(location.href);   // https://www.runoob.com/js/js-window-location.html

跳转到新的页面

window.location.href="http://www.jb51.net";      //在同当前窗口中打开窗口

5.4.2 Window Location Pathname

location.pathname 属性返回 URL 的路径名。

document.write(location.pathname); //  /js/js-window-location.html
5.4.3 Window Location Assign

location.assign() 方法加载新的文档。

<head>
<script>
function newDoc(){
    window.location.assign("https://www.runoob.com")
}
</script>
</head>
<body>
 
<input type="button" value="加载新文档" onclick="newDoc()">

5.5 Window History

window.history 对象包含浏览器的历史。

window.history对象在编写时可不使用 window 这个前缀。

5.5.1 Window history.back()

history.back() 方法加载历史列表中的前一个 URL。
这与在浏览器中点击后退按钮是相同的:

function goBack()
{
    window.history.back()
}

5.5.2 Window history.forward()

history forward() 方法加载历史列表中的下一个 URL。
这与在浏览器中点击前进按钮是相同的:

function goForward()
{
    window.history.forward()
}

5.5.3 Window history.go()

可以用 history.go() 这个方法来实现向前,后退和刷新本页的功能。

function a(){
    history.go(0);  // go() 里面的参数为0,表示刷新页面
}
function b(){
    history.go(1);  // go() 里面的参数表示跳转页面的个数 例如 history.go(1) 表示前进一个页面
}
function c(){
    history.go(-1);  // go() 里面的参数表示跳转页面的个数 例如 history.go(-1) 表示后退一个页面
}

5.6 Window Navigator

window.navigator 对象包含有关访问者浏览器的信息。

<div id="example"></div>
<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.systemLanguage + "</p>";
document.getElementById("example").innerHTML=txt;
</script>

5.7 JavaScript 弹窗

可以在 JavaScript 中创建三种消息框:警告框、确认框、提示框。

5.7.1 警告框

警告框经常用于确保用户可以得到某些信息。

当警告框出现后,用户需要点击确定按钮才能继续进行操作。

语法:window.alert("sometext"); 或者alert("sometext");

function myFunction()
{
    alert("你好,我是一个警告框!");
}

5.7.2 确认框

确认框通常用于验证是否接受用户操作。

当确认卡弹出时,用户可以点击 “确认” 或者 “取消” 来确定用户操作。

当你点击 “确认”, 确认框返回 true, 如果点击 “取消”, 确认框返回 false。

语法:window.confirm("sometext");或者confirm("sometext");

<button onclick="myFunction()">点我</button>
<p id="demo"></p>
<script>
function myFunction(){
	var x;
	var r=confirm("按下按钮!");
	if (r==true){
		x="你按下了\"确定\"按钮!";
	}
	else{
		x="你按下了\"取消\"按钮!";
	}
	document.getElementById("demo").innerHTML=x;
}
</script>

5.7.3 提示框

提示框经常用于提示用户在进入页面前输入某个值。

当提示框出现后,用户需要输入某个值,然后点击确认或取消按钮才能继续操纵。

如果用户点击确认,那么返回值为输入的值。如果用户点击取消,那么返回值为 null。

语法:window.prompt("sometext","defaultvalue");或者prompt("sometext","defaultvalue");

<button onclick="myFunction()">点我</button>
<p id="demo"></p>
<script>
function myFunction(){
	var x;
	var person=prompt("请输入你的名字","Harry Potter");
	if (person!=null && person!=""){
	    x="你好 " + person + "! 今天感觉如何?";
	    document.getElementById("demo").innerHTML=x;
	}
}
</script>

5.8 JavaScript 计时事件

通过使用 JavaScript,我们有能力做到在一个设定的时间间隔之后来执行代码,而不是在函数被调用后立即执行。

5.8.1 setInterval() 方法

setInterval() 间隔指定的毫秒数不停地执行指定的代码

<p>在页面显示一个时钟</p>
<p id="demo"></p>
<script>
var myVar=setInterval(function(){myTimer()},1000);
function myTimer(){
	var d=new Date();
	var t=d.toLocaleTimeString();
	document.getElementById("demo").innerHTML=t;
}
</script>

5.8.2 clearInterval() 方法

clearInterval() 方法用于停止 setInterval() 方法执行的函数代码。

要使用 clearInterval() 方法, 在创建计时方法时你必须使用全局变量:

<script>
var myVar=setInterval(function(){myTimer()},1000);
function myTimer(){
    var d=new Date();
    var t=d.toLocaleTimeString();
    document.getElementById("demo").innerHTML=t;
}
function myStopFunction(){
    clearInterval(myVar);
}
</script>

5.8.3 setTimeout() 方法

setTimeout() 经过指定的毫秒数之后执行指定的代码

setTimeout(function(){alert("Hello")},3000);

5.8.4 clearTimeout() 方法

setTimeout() 还未被执行,可以使用 clearTimeout() 方法来停止执行函数代码。

要使用clearTimeout() 方法, 你必须在创建超时方法中(setTimeout)使用全局变量:

var myVar;
 
function myFunction()
{
    myVar=setTimeout(function(){alert("Hello")},3000);
}
 
function myStopFunction()
{
    clearTimeout(myVar);
}

5.9 JavaScript Cookie

由于HTTP是一种无状态的协议,服务器单从网络连接上是无法知道客户身份的。这时候服务器就需要给客户端颁发一个cookie,用来确认用户的身份。

Cookie 用于存储 web 页面的用户信息。

Cookie 是一些数据, 存储于你电脑上的文本文件中(浏览器)。

Cookie 以名/值对形式存储,如下所示:

username=John Doe

5.9.1 创建Cookie

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

JavaScript 中,创建 cookie 如下所示:

document.cookie="username=John Doe";

设置 cookie 值的函数

function setCookie(cname,cvalue,exdays)
{
  var d = new Date();
  d.setTime(d.getTime()+(exdays*24*60*60*1000));
  var expires = "expires="+d.toGMTString();
  document.cookie = cname + "=" + cvalue + "; " + expires;
}

5.9.2 读取 Cookie

在 JavaScript 中, 可以使用以下代码来读取 cookie:

var x = document.cookie;

获取 cookie 值的函数

function getCookie(cname)
{
  var name = cname + "=";
  var ca = document.cookie.split(';');
  for(var i=0; i<ca.length; i++) 
  {
    var c = ca[i].trim();
    if (c.indexOf(name)==0) return c.substring(name.length,c.length);
  }
  return "";
}

5.9.3 删除 Cookie

删除 cookie 非常简单。您只需要设置 expires 参数为以前的时间即可,如下所示,设置为 Thu, 01 Jan 1970 00:00:00 GMT:

document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT";

5.9.4 jquery.cookie() 方法

jquery中操作cookie的方式

1.新添加一个会话 cookie:
$.cookie('the_cookie', 'the_value');
2.读取cookie:
$.cookie('the_cookie'); // cookie存在 => 'the_value' cookie不存在 => null
3.删除cookie:
$.cookie('the_cookie', null);

5.10 其他 Window 方法

5.10.1 window.open() 方法

open() 方法用于打开一个新的浏览器窗口或查找一个已命名的窗口。
语法:window.open(URL,name,specs,replace)

URL: 可选。打开指定的页面的URL。如果没有指定URL,打开一个新的空白窗口

name:可选。指定target属性或窗口的名称。支持以下值:

  • _blank - URL加载到一个新的窗口。这是默认
  • _parent - URL加载到父框架
  • _self - URL替换当前页面
  • _top - URL替换任何可加载的框架集

specs:可选。一个逗号分隔的项目列表。指定新建窗口的属性。

window.open("http://www.runoob.com");     //在新建窗口中打开窗口

5.10.2 window.close() 方法

close() 方法用于关闭浏览器窗口。

window.close()

5.10.3 window.scrollTo() 方法

scrollTo() 方法可把内容滚动到指定的坐标。
语法:scrollTo(xpos,ypos)

5.10.3.1 实际运用:返回顶部
window.scrollTo(0, 0)

六、其他问题

6.1 如何阻止事件冒泡以及默认行为

阻止事件冒泡

DOM中提供stopPropagation()方法,使用event对象在事件函数中调用就行。但IE不支持。

IE中提供的是,cancelBubble属性,默认为false,当它设置为true时,就是阻止事件冒泡,也是用event对象在事件函数中调用

function stopBubble(e) {  
 if(e && e.stopPropagation){  
      e.stopPropagation();  
  } else {  
    window.event.cancelBubble = true;  
  }  
};  

阻止默认行为

DOM中提供preventDefault()方法来取消事件默认行为,但是只有当cancelable属性设置为true的事件,才可以使用preventDefault()来取消事件默认行为,使用event对象在事件函数中调用就行

IE中提供的是returnValue属性,默认为true,当它设置为false时,就是取消事件默认行为,也是用event对象在事件函数中调用

function stopDefault(e){  
   if(e && e.preventDefault) {  
      e.preventDefault();  
   } else {  
      window.event.returnValue = false;  
   }  
   return false;  
  }; 

6.2 setTimeout(fn,0)理解

  • 在JS操作中会有两个线程,一个是主线程执行所有的同步任务,另一个是执行异步操作的任务队列
  • JS会优先读取执行中的同步任务 然后在去读取任务队列里的异步任务,这个过程称为事件循环(Event Loop)

所以当setTimeout(fn,0)执行时,会在异步队列中添加一个消息。如果异步队列没有其他消息,则会被马上处理。但是如果有其他消息必须等待其他消息处理完成。

setTimeout(function() {
     console.log(1);
 },0);
 console.log(2)复制代码

// 执行结果: 先输出2,在输出1
// 主线程空了,才会去任务队列中取任务执行回调函数。

6.3 JavaScript原始数据类型和引用类型

6.3.1 值类型/原始类型/基本类型

值类型在赋值操作时将变量的内容赋值给新的变量

  • undefined
  • null
  • Boolean
  • String
  • Number
  • Symbol

6.3.2 引用类型(对象)

引用类型在赋值操作时是将指向变量的指针赋值给新的变量,修改其中一个变量的值,另一个会一起改变

  • {} 对象
  • [] 数组

6.3.3 基本类型和引用类型的区别

不同的存储方式:

  • 基本类型:基本类型值在内存中占据固定大小,保存在栈内存中。
  • 引用类型:引用类型的值是对象,保存在堆内存中,而栈内存存储的是对象的变量标识符和对象在堆内存的存储地址。

不同的复制方式:

  • 基本类型:从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本,并将该副本复制给新变量。

    let foo = 1;
    let bar = foo;
    console.log(foo === bar); // -> true
    
    // 修改foo变量的值并不会影响bar变量的值
    let foo = 233;
    console.log(foo); // -> 233
    console.log(bar); // -> 1
    
  • 引用类型:从一个变量向另一个变量复制引用类型的值,复制的是指针,最终两个变量都指向同一个对象。

    let foo = {
      name: 'leeper',
      age: 20
    }
    let bar = foo;
    console.log(foo === bar); // -> true
    
    // 改变foo变量的值会影响bar变量的值
    foo.age = 19;
    console.log(foo); // -> {name: 'leeper', age: 19}
    console.log(bar); // -> {name: 'leeper', age: 19}
    

6.4 函数防抖和函数节流

6.4.1 函数防抖(debounce)

函数防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

const _.debounce = (func, wait) => {
  let timer;

  return () => {
    if(timer) clearTimeout(timer);
    timer = setTimeout(func, wait);
  };
};

应用场景:
连续的事件,只需触发一次回调的场景有:

  • 搜索框搜索输入。只需用户最后一次输入完,再发送请求
  • 手机号、邮箱验证输入检测
  • 窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。

6.4.2 函数节流(throttle)

限制一个函数在一定时间内只能执行一次。防止页面点击事件触发多次点击

const _.throttle = (func, wait) => {
  let timer;

  return () => {
    if (timer) {
      return;
    }

    timer = setTimeout(() => {
      func();
      timer = null;
    }, wait);
  };
};

应用场景:
间隔一段时间执行一次回调的场景有:

  • 滚动加载,加载更多或滚到底部监听
  • 谷歌搜索框,搜索联想功能
  • 高频点击提交,表单重复提交

区别:防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。

6.5 什么是类数组对象?

  • 一个拥有 length 属性和若干索引属性的对象就可以被称为类数组对象。
  • 类数组对象和数组类似,但是不能调用数组的方法。
  • 常见的类数组对象有 arguments 和 DOM 方法的返回结果,还有一个函数也可以被看作是类数组对象,因为它含有 length 属性值,代表可接收的参数个数。

常见的类数组转换为数组的方法有以下4种:

//(1)通过 call 调用数组的 slice 方法来实现转换
Array.prototype.slice.call(arrayLike);

//(2)通过 call 调用数组的 splice 方法来实现转换
Array.prototype.splice.call(arrayLike, 0);

//(3)通过 apply 调用数组的 concat 方法来实现转换
Array.prototype.concat.apply([], arrayLike);

//(4)通过 Array.from 方法来实现转换
Array.from(arrayLike);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值