从零开始JavaScript学习第10天笔记
一.BOM(浏览器对象模型)
当涉及到JavaScript与浏览器之间的交互时,我们会使用浏览器对象模型(BOM)。BOM 提供了许多对象,使我们能够操纵浏览器窗口、文档、历史记录等。
1.Window对象
1.alert()
alert(message) 是一个用于显示一个警告框(弹窗)的函数。它接受一个参数 message,用于指定要在弹窗中显示的文本消息。
当 alert(message) 被调用时,会弹出一个对话框,其中包含了传入的 message 文本。用户可以点击对话框上的确定按钮来关闭弹窗。
var message = "Hello, World!";
alert(message); // 显示警告框,其中包含了 "Hello, World!" 文本
2.confirm()
confirm() 是 window 对象的一个方法,用于显示一个确认框,提供给用户一个选择。确认框通常用于询问用户是否确定执行某个操作。
if (confirm("您确定要删除该文件吗?")) {
// 用户点击了确认按钮
// 执行删除文件的操作
} else {
// 用户点击了取消按钮
// 取消删除文件的操作
}
当你点击确认时,返回值为true。点击取消时,返回值为false。
3.prompt()
prompt() 是 window 对象的一个方法,用于显示一个输入框,要求用户输入信息。输入框通常用于获取用户输入的数据。
语法:prompt(message, defaultText)
其中,message 是一个可选的字符串参数,用于指定在输入框前显示的提示信息。defaultText 是一个可选的字符串参数,用于指定输入框中的默认文本。
返回值:
当用户点击输入框中的“确定”按钮时,prompt() 方法返回用户在输入框中输入的文本。
当用户点击输入框中的“取消”按钮时,prompt() 方法返回 null。
let name = prompt("请输入您的姓名:", "张三");
if (name != null) {
// 用户点击了确定按钮并输入了姓名
console.log("您好," + name + "!");
} else {
// 用户点击了取消按钮
console.log("您没有输入姓名。");
}
4.open()
open() 是 window 对象的一个方法,用于打开新的浏览器窗口或标签页。
语法:window.open(url, target, features, replace)
参数说明:
url:可选参数,表示要打开的 URL 地址。如果不指定 URL,则打开一个空白页面。
target:可选参数,表示打开链接的目标窗口或标签页。可以是一个已存在的窗口或标签页的名称,或者以下特殊值之一:
_blank:在新窗口或标签页中打开链接(默认行为)。
_self:在当前窗口或标签页中打开链接。
_parent:在父级窗口或标签页中打开链接。
_top:在最顶层的窗口或标签页中打开链接。
features:可选参数,表示新窗口的特性,如大小、位置、工具栏、地址栏等。这是一个字符串,可以包含一个或多个窗口特性的名称和值,用逗号分隔。例如,“width=500,height=400,toolbar=no”。
replace:可选参数,表示是否用新的 URL 替换浏览器历史记录中的当前页面。如果设置为 true,则在打开新窗口时将替换当前页面的 URL;如果设置为 false 或不提供该参数,则在新窗口中打开新页面,并保留原页面的历史记录。
window.open('https://www.example.com', '_blank', 'width=500,height=400');
上述代码将在新窗口中打开 https://www.example.com 网页,并设置新窗口的宽度为 500 像素,高度为 400 像素。
二.JavaScript 的内置方法
JavaScript 的内置方法是指由 JavaScript 语言本身提供的方法,它们可以直接在代码中使用,无需额外导入或安装。
1.计时器
有两种常用的计时器:setTimeout 和 setInterval。
1.setTimeout
setTimeout 方法用于在一定的延迟时间后执行一次指定的函数。
语法:setTimeout(function, delay)
参数:
function:要执行的函数或要评估的代码。
delay:延迟的毫秒数。 返回值:一个唯一的定时器 ID,可以通过 clearTimeout 方法取消计时器。
function sayHello() {
console.log("Hello!");
}
setTimeout(sayHello, 2000);
上述代码中,定义了一个名为 sayHello 的函数,然后使用 setTimeout 方法在延迟 2000 毫秒(即2秒)后执行该函数,控制台将输出 “Hello!”。
2.setInterval
setInterval 方法用于每隔一定的时间重复执行指定的函数。
语法:setInterval(function, delay)
参数:
function:要执行的函数或要评估的代码。
delay:每次执行之间的间隔时间(以毫秒为单位)。 返回值:一个唯一的定时器 ID,可以通过 clearInterval 方法取消计时器。
let count = 0;
function increment() {
count++;
console.log("Count: " + count);
}
setInterval(increment, 1000);
上述代码中,定义了一个变量 count 和一个名为 increment 的函数。使用 setInterval 方法每隔 1000 毫秒(即1秒)执行一次 increment 函数,每次执行时 count 值增加 1,控制台将输出当前的 count 值。
2.console
console 是一个内置对象,用于在浏览器的控制台打印输出信息,方便开发和调试代码。console 对象提供了一系列方法来输出不同类型的信息。
1.console.log()
console.log() 是 console 对象的一个方法,用于将信息打印到浏览器的控制台。它接受一个或多个参数,并在控制台中打印它们的值。
console.log("Hello, World!"); // 打印字符串 "Hello, World!"
const x = 10;
console.log("The value of x is", x); // 打印字符串 "The value of x is" 和变量 x 的值
const fruits = ["apple", "banana", "orange"];
console.log(fruits); // 打印数组 fruits 的内容
console.log({ name: "John", age: 30 }); // 打印对象的内容
console.log("Name:", "John", "Age:", 30); // 打印多个参数的值
console.log(`The answer is ${x}`); // 打印带有变量值的模板字符串
2.console.dir()
console.dir() 是 console 对象的一个方法,用于以一种更详细的方式打印对象的属性和方法。它接受一个对象作为参数,并在控制台中以树状结构显示该对象的详细信息。
const person = {
name: "John",
age: 30,
address: {
city: "New York",
country: "USA"
}
};
console.dir(person); // 打印对象 person 的详细信息
3.console.debug()
console.debug() 是 console 对象的一个方法,用于在控制台中打印调试信息。它接受一个或多个参数,并将它们作为调试信息输出到控制台。
const num1 = 10;
const num2 = 20;
console.debug("The value of num1 is:", num1);
console.debug("The value of num2 is:", num2);
在控制台中,console.debug() 方法会将传递给它的参数作为调试信息输出。通常,调试信息会以不同的方式显示,例如带有特殊的标记或颜色。这有助于开发者更清楚地辨认调试信息,以便在调试代码时更方便地定位问题。
4.console.time和console.timeEnd
console.time和console.timeEnd是用于测量代码执行时间的方法。
console.time("myTimer");
for (var i = 0; i < 1000000; i++) {
// 一些耗时的操作
}
console.timeEnd("myTimer");//打印myTimer: 2.698974609375 ms
5.console.clear()
console.clear()是用于清除浏览器控制台中的所有输出信息的方法。
console.log("这是一条日志信息");
console.log("这是另一条日志信息");
console.clear();
我们首先输出了两条日志信息,然后调用console.clear()方法。这将清除控制台中的所有输出信息,使控制台变为空白。
6.console.error()
当我们在代码中遇到错误或异常时,可以使用console.error()方法将错误信息输出到控制台,以便我们进行调试和查找问题所在。
console.error("这是一个错误信息");
onsole.error()方法只会输出错误信息,并不会中断代码的执行。因此,即使有错误信息输出到控制台,代码仍然会继续执行。如果希望在遇到错误时中断代码的执行,可以使用throw语句抛出错误。
7.console.warn()
当我们在代码中遇到一些可能会导致问题或潜在错误的情况时,可以使用console.warn()方法将警告信息输出到控制台,以便我们进行调试和查找问题所在。
console.warn("这是一个警告信息");
console.warn("这是一个", "警告信息");
8.console.info()
console.info()方法与console.log()方法非常相似,都可以用来输出信息到控制台。它们的使用方式和效果都是一样的。
console.info("这是一条信息");
console.info("这是一条", "信息");
它主要用于提供额外的、有用的信息给开发人员,帮助他们进行调试。
9.console.table()
在JavaScript中,console.table()是用于以表格形式打印数组或对象的方法。
const fruits = [
{ name: "apple", color: "red", price: 0.5 },
{ name: "banana", color: "yellow", price: 0.25 },
{ name: "orange", color: "orange", price: 0.3 }
];
console.table(fruits);
console.table()方法是用于以表格形式打印数组或对象的方法,可以在控制台中更清晰地显示复杂数据结构的信息。
3.parseInt()
parseInt()实际上是JavaScript的全局方法,全局方法是在JavaScript运行时环境中直接可用的函数,无需导入或实例化。
语法:parseInt(string, radix)
其中,string 是要解析的字符串,radix 是一个可选参数,指定要解析的字符串的基数(进制)。如果不提供 radix 参数,则默认为 10。
const num1 = parseInt("10");
console.log(num1); // 输出:10
const num2 = parseInt("10", 2);
console.log(num2); // 输出:2,将二进制的10转换为十进制
const num3 = parseInt("A", 16);
console.log(num3); // 输出:10,将十六进制的A转换为十进制
const num4 = parseInt("1010", 2);
console.log(num4); // 输出:10,将二进制的1010转换为十进制
需要注意的是,parseInt()函数会忽略字符串中非数字字符后面的字符。如果字符串以非数字字符开头,parseInt()函数会返回NaN。如果字符串无法解析为整数,parseInt()函数也会返回NaN。
一道练习题
var arr = [1, "0", "131"]
var arr2 = arr.map(parseInt)
console.log(arr2)//输出[1,NaN,1]
先明白map的作用之后,再想想就parseInt的作用就懂了。输入然后运行就可以了。
三.ES6(ECMAScript 2015)
1.声明关键字
1.let
let 是 ES6(ECMAScript 2015)中引入的关键字之一。它用于声明块级作用域的变量,相对于之前的 var 关键字,let 提供了更好的变量作用域控制。
使用 let 声明的变量具有块级作用域,即只在声明它的代码块内有效。与 var 声明的变量不同,let 声明的变量不会被提升到当前作用域的顶部。
if (true) {
let x = 10;
console.log(x); // 输出 10
}
console.log(x); // 报错 x未定义
{
let i = 20 //暂时性死区
var j = 30
}
console.log(j)//输出 30
console.log(i)//报错
这种块级作用域的特性使得 let 更适合用于循环或条件语句中,以及任何需要限制作用域范围的场景。
2.const
const 是 ES6(也称为 ECMAScript 2015)引入的新特性之一。const 关键字用于声明一个常量,可以在声明时初始化赋值,并且一旦赋值后,其值不能被修改。在 ES6 之前,JavaScript 只有 var 关键字用于声明变量,没有直接的方式声明常量。引入 const 关键字使得开发者能够更清晰地表达出某些变量是常量,并且提供了更好的代码可读性和维护性。
const PI = 3.14159;
console.log(PI); // 输出 3.14159
PI = 3.14; // 抛出 TypeError: Assignment to constant variable.
const person = {
name: 'John',
age: 30
};
person.name = 'Jane';
console.log(person.name); // 输出 'Jane'
person = {}; // 抛出 TypeError: Assignment to constant variable.
2.解构赋值
ES6 中的解构赋值是一种方便的语法,可以从数组或对象中提取值,并将它们赋给新的变量。
1.数组解构赋值
通过模式匹配的方式,将数组中的元素赋值给对应的变量。
底层逻辑大概是
1.创建一个临时变量,保存要解构的数组。
2.检查临时变量是否是可迭代对象,如果不是,则抛出 TypeError。
3.遍历临时变量,获取对应位置的值,依次赋给对应的变量。
4.如果目标变量个数大于数组中的元素个数,则未被解构的变量值为 undefined。
5.如果数组解构表达式中有默认值,当对应位置的值为 undefined 时,使用默认值进行赋值。
const array = [1, 2, 3];
const [a, b, c] = array;
console.log(a); // 输出: 1
console.log(b); // 输出: 2
console.log(c); // 输出: 3
2.对象解构赋值
通过模式匹配的方式,将对象中的属性值赋值给对应的变量。
const object = { x: 1, y: 2 };
const { x, y } = object;
console.log(x); // 输出: 1
console.log(y); // 输出: 2
底层逻辑大概是
1.创建一个临时变量,保存要解构的对象。
2.检查临时变量是否是对象类型,如果不是,则抛出 TypeError。
3.根据对象解构表达式中的属性名,从临时变量中获取对应的属性值,依次赋给对应的变量。
4.如果对象解构表达式中有默认值,当对应属性值为 undefined 时,使用默认值进行赋值。
带有默认值的题
const array = [1, 2];
const [a = 0, b = 0, c = 0] = array;
console.log(a); // 输出: 1
console.log(b); // 输出: 2
console.log(c); // 输出: 0
const object = { x: 1 };
const { x, y = 2 } = object;
console.log(x); // 输出: 1
console.log(y); // 输出: 2
3.其他进制的数字写法
1.二进制数字
在ES6中,可以使用前缀0b来表示二进制数。
const binaryNumber = 0b101010; // 表示十进制的 42
console.log(binaryNumber); // 输出 42
2.八进制数字
在ES6中,可以使用前缀0o来表示八进制数。
const octalNumber = 0o52; // 表示十进制的 42
console.log(octalNumber); // 输出 42
3.十六进制数字
在ES6中,可以使用前缀0x来表示十六进制数。
const hexadecimalNumber = 0x2A; // 表示十进制的 42
console.log(hexadecimalNumber); // 输出 42
4.ES6中数组新方法
1.Array.of()方法
在ES6中,引入了Array.of()方法,用于创建一个包含任意数量参数的新数组。
语法:Array.of(element0[, element1[, …[, elementN]]])
参数element0到elementN是要包含在新数组中的元素。
const arr = Array.of(1, 2, 3, 4, 5);
console.log(arr); // 输出 [1, 2, 3, 4, 5]
const arr1 = Array(5);
console.log(arr1); // 输出 [...]
const arr2 = Array.of(5);
console.log(arr2); // 输出 [5]
2.Array.from()方法
Array.from() 方法用于将类数组对象或可迭代对象转换为真正的数组。它接受一个类数组对象或可迭代对象作为参数,并返回一个新的数组。
语法:Array.from(arrayLike [, mapFn [, thisArg]])
参数说明:
arrayLike:需要转换为数组的类数组对象或可迭代对象。
mapFn (可选):对数组的每个元素进行处理的映射函数。
thisArg (可选):映射函数执行时的this值。
const str = 'hello';
const arr = Array.from(str);
console.log(arr); // 输出 ['h', 'e', 'l', 'l', 'o']
const set = new Set([1, 2, 3, 4, 5]);
const arr2 = Array.from(set, x => x * 2);
console.log(arr2); // 输出 [2, 4, 6, 8, 10]
5.ES6中Object的拓展
1.Symobol基础数据
在ES6中,Symbol是一种新增的基本数据类型,用于创建唯一的、不可变的值。它的作用是用作对象属性的标识符,可以防止属性名冲突。
Symbol的创建方式是使用全局函数Symbol(),它返回一个唯一的Symbol值。Symbol值可以用作对象的属性名,以确保属性名的唯一性。
let sym1 = Symbol();
let sym2 = Symbol('key');
let obj = {
[sym1]: 'value1',
[sym2]: 'value2'
};
console.log(obj[sym1]); // 输出:value1
console.log(obj[sym2]); // 输出:value2
2.拷贝
1.Object.values()
在ES6中,Object.values()方法是用于返回一个给定对象自身的所有可枚举属性值的数组。
const obj = {
name: 'John',
age: 30,
address: 'New York'
};
const values = Object.values(obj);
console.log(values); // ['John', 30, 'New York']
另一个拷贝问题
let obj = { a: 300, a: 100, b: 200, x: { y: 66666 } }
var obj2 = { ...obj }
obj2.x.y = 9999
console.log(obj)
console.log(obj2, obj, obj == obj2, obj.x === obj2.x)
//输出obj obj flase true
样拷贝就会出现一个问题,引用数据没完全独立出来,还是指向原来的对象。
2.深拷贝
1.使用Object.assign()方法进行深拷贝:
let obj1 = {
name: 'John',
age: 30,
address: {
city: 'New York',
country: 'USA'
}
};
let obj2 = Object.assign({}, obj1);
console.log(obj2);
上述代码中,使用Object.assign()方法将obj1对象的属性复制到一个新的空对象中,实现了obj1对象的深拷贝。修改obj2对象的属性不会影响到obj1对象。
2.使用扩展运算符(…)进行深拷贝:
let obj1 = {
name: 'John',
age: 30,
address: {
city: 'New York',
country: 'USA'
}
};
let obj2 = {...obj1};
console.log(obj2);
需要注意的是,以上的深拷贝方法只能深拷贝对象的第一层属性,如果对象的属性值是引用类型(如数组、对象等),则只会复制引用,而不是真正的拷贝。如果需要深拷贝引用类型的属性值,可以使用递归或者第三方库(如Lodash的cloneDeep方法)来实现。
const deepClone = (obj) => {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
let newObj = Array.isArray(obj) ? [] : {};
for (let key in obj) {
newObj[key] = deepClone(obj[key]);
}
return newObj;
};
let obj1 = {
name: 'John',
age: 30,
address: {
city: 'New York',
country: 'USA'
}
};
let obj2 = deepClone(obj1);
console.log(obj2);
3.使用原函数的构造函数来构建一个新的对象
var copy1 = function (obj) {
if(obj === null) return null
if(typeof obj !== 'object') return obj;
if(obj.constructor===Date) return new Date(obj);
if(obj.constructor === RegExp) return new RegExp(obj);
var newObj = new obj.constructor (); //保持继承链
for (var key in obj) {
if (obj.hasOwnProperty(key)) { //不遍历其原型链上的属性
var val = obj[key];
newObj[key] = typeof val === 'object' ? arguments.callee(val) : val; // 使用arguments.callee解除与函数名的耦合
}
}
return newObj;
};