文章目录
- 一、JavaScript基础
- 二、JavaScript 对象
- 2.1 Date 对象
- 2.2 Math 对象
- 2.4 Array 对象
- 2.4.1 length 属性
- 2.4.2 toString() 方法
- 2.4.3 join() 方法
- 2.4.4 sort() 方法
- 2.4.5 pop() 方法
- 2.4.6 push() 方法
- 2.4.7 shift() 方法
- 2.4.8 unshift() 方法
- 2.4.9 slice() 方法
- 2.4.10 splice() 方法
- 2.4.11 forEach() 方法
- 2.4.12 map() 方法
- 2.4.13 filter() 方法
- 2.4.14 reduce() 方法
- 2.4.15 every() 方法
- 2.4.16 some() 方法
- 2.4.16 indexOf() 方法
- 2.4.17 lastIndexOf() 方法
- 2.4.18 find() 方法
- 2.4.19 findIndex() 方法
- 2.4.20 includes() 方法
- 2.3 String 对象
- 2.4 JSON 对象
- 三、call() apply() bind() 的用法
- 四、HTML DOM
- 五、Window - 浏览器对象模型
- 六、其他问题
一、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()。
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 来自 成都去往上海
以下示例通过bind
给document
添加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型参数
- 先说Boolean型参数,如果为true,元素的顶端将和其所在滚动区的可视区域的顶端对齐。若为false,元素的底端将和其所在滚动区的可视区域的底端对齐。
- 之后是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);