JavaScript

感觉JavaScript里面还有很多基础的细节没搞明白,开个坑专门存一下。

转义特殊字符

如果要匹配的 ID 或选择器不符合 CSS 语法(比如不恰当地使用了冒号或者空格),你必须用反斜杠将这些字符转义。由于 JavaScript 中,反斜杠是转义字符,所以当你输入一个文本串时,你必须将它转义两次(一次是为 JavaScript 字符串转义,另一次是为 querySelector 转义):

<div id="foo\bar"></div>
<div id="foo:bar"></div>

<script>
  console.log('#foo\bar')               // "#fooar"
  document.querySelector('#foo\bar')    // 不匹配任何元素

  console.log('#foo\\bar')              // "#foo\bar"
  console.log('#foo\\\\bar')            // "#foo\\bar"
  document.querySelector('#foo\\\\bar') // 匹配第一个 div

  document.querySelector('#foo:bar')    // 不匹配任何元素
  document.querySelector('#foo\\:bar')  // 匹配第二个 div
</script>

//补充:document.querySelector选择器特殊使用
/*
这里,一个 class 属性为"user-panel main"的 div 元素
<div>(<div class="user-panel main">) 
内包含一个 name 属性为"login"的 input 元素
<input> (<input name="login"/>) 
如何选择,如下所示:
*/
var el = document.querySelector("div.user-panel.main input[name='login']");
转义字符译义
\ ?在书写连续多个问好时使用,防止他们被解析成三字母词
\ ’用于表示字符常量‘
\ "用于表示字符常量"
\ \用于表示一个反斜杠,防止他被解译成一个转义字符
\ a警告字符,表示:蜂鸣
\ b退格符
\ f换页符
\ n换行符
\ r回车符
\ t水平制表符
\ v垂直制表符
\ ddd三位八进制数代表一个ASCII字符(ddd是一个八进制数字)
\ xdd二为十六进制数代表一个ASCII字符(dd是一个十六进制数字)

var、let、const异同

1)作用域

用 var 声明的变量的作用域是它当前的执行上下文,即如果是在任何函数外面,则是全局执行上下文,如果在函数里面,则是当前函数执行上下文。换句话说,var 声明的变量的作用域只能是全局或者整个函数块的。

而 let 声明的变量的作用域则是它当前所处代码块,即它的作用域既可以是全局或者整个函数块,也可以是 if、while、switch等用{}限定的代码块。

另外,var 和 let 的作用域规则都是一样的,其声明的变量只在其声明的块或子块中可用。

function varTest() {
  var a = 1;

  {
    var a = 2; // 函数块中,同一个变量
    console.log(a); // 2
  }
  
  console.log(a); // 2
}

function letTest() {
  let a = 1;

  {
    let a = 2; // 代码块中,新的变量
    console.log(a); // 2
  }
  
  console.log(a); // 1
}

let 声明的作用域比 var 声明的作用域有更小的限定范围,更具灵活。

2)重复性

var 允许在同一作用域中重复声明,而 let 不允许,否则将抛出异常。

var a = 1;
var a = 2;

console.log(a) // 2

 let a = 1;
 let a = 2; // SyntaxError: Identifier 'a' has already been declared
3)绑定全局对象

var 在全局环境声明变量,会在全局对象里新建一个属性,而 let 在全局环境声明变量,则不会在全局对象里新建一个属性。

var foo = 'global'
let bar = 'global'

console.log(this.foo) // global
console.log(this.bar) // undefined
  • let 在全局环境声明变量 bar 保存在 [[Scopes]][0]: Script 这个变量的属性中;
  • 而 [[Scopes]][1]: Global 就是我们常说的全局对象。
4)变量提升与暂存死区
  1. var 声明的变量在执行上下文创建阶段就会被「创建」和「初始化」,因此对于执行阶段来说,可以在声明之前使用。
  2. let 声明的变量在执行上下文创建阶段只会被「创建」而不会被「初始化」,因此对于执行阶段来说,如果在其定义执行前使用,相当于使用了未被初始化的变量,会报错。
//示例代码 1:

console.log(bar); // undefined
console.log(foo); // ReferenceError: foo is not defined

var bar = 1;
let foo = 2;


//示例代码 2:

var foo = 33;
{
  let foo = (foo + 55); // ReferenceError: foo is not defined
}
5)const变量

const 与 let 很类似,都具有上面提到的 let 的特性,唯一区别就在于 const 声明的是一个只读变量,声明之后不允许改变其值。因此,const 一旦声明必须初始化,否则会报错。

let a;
const b = "constant"

a = "variable"
b = 'change' // TypeError: Assignment to constant variable

如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量。

// 此处可调用 carName 变量
//此处可使用 window.carName
 
function myFunction() {
    carName = "Volvo";
    // 此处可调用 carName 变量
}
  • JavaScript 变量生命周期在它声明时初始化。

  • 局部变量在函数执行完毕后销毁。

  • 全局变量在页面关闭后销毁。

  1. 使用var关键字声明的全局作用域变量属于window对象。

  2. 使用let关键字声明的全局作用域变量不属于window对象。

  3. 使用var关键字声明的变量在任何地方都可以修改。

  4. 在相同的作用域或块级作用域中,不能使用let关键字来重置var关键字声明的变量。

  5. 在相同的作用域或块级作用域中,不能使用let关键字来重置let关键字声明的变量。

  6. let关键字在不同作用域,或不用块级作用域中是可以重新声明赋值的。

  7. 在相同的作用域或块级作用域中,不能使用const关键字来重置var和let关键字声明的变量。

  8. 在相同的作用域或块级作用域中,不能使用const关键字来重置const关键字声明的变量

  9. const 关键字在不同作用域,或不同块级作用域中是可以重新声明赋值的:

  10. var关键字定义的变量可以先使用后声明。

  11. let关键字定义的变量需要先声明再使用。

  12. const关键字定义的常量,声明时必须进行初始化,且初始化后不可再修改

数据类型

1.使用 constructor 属性来查看对象
//判断是否为数组
function isArray(myArray) {
    return myArray.constructor.toString().indexOf("Array") > -1;
}

//判断是否为日期对象
function isDate(myDate) {
    return myDate.constructor.toString().indexOf("Date") > -1;
}
2.类型转换的多种方法
//转化为字符    x可为数字、布尔值、日期

String(x)
x.toString()   //甚至可以转换函数function 结果为整个函数体( function myFunction(a, b) {...} )

//转化为数字
/*全局方法 Number() 可以将字符串转换为数字。
字符串包含数字(如 "3.14") 转换为数字 (如 3.14).
空字符串转换为 0。
其他的字符串会转换为 NaN (不是个数字)。*/

Number(x)       //x可为布尔值、日期、字符;无效字符会转换成NaN
parseFloat()	//解析一个字符串,并返回一个浮点数。
parseInt()	    //解析一个字符串,并返回一个整数。



//自动转换类型

5 + null    // 返回 5         null 转换为 0
"5" + null  // 返回"5null"   null 转换为 "null"
"5" + 1     // 返回 "51"      1 转换为 "1" 
"5" - 1     // 返回 4         "5" 转换为 5

正则表达式

var patt = /runoob/i

实例解析:

  • /runoob/i 是一个正则表达式。

  • runoob 是一个正则表达式主体 (用于检索)。

  • i 是一个修饰符 (搜索不区分大小写)。(g-执行全局匹配(查找所有匹配),m-执行多行匹配)

1.使用字符串方法
  1. search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,并返回子串的起始位置。

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

  3. test() 方法用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回 true,否则返回 false。

  4. exec() 方法用于检索字符串中的正则表达式的匹配。该函数返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。

2.正则表达式规则
表达式描述
[abc]查找方括号之间的任何字符。
[0-9]查找任何从 0 至 9 的数字。
(xy)
元字符描述
\d查找数字。
\s查找空白字符。
\b匹配单词边界。
\uxxxx查找以十六进制数 xxxx 规定的 Unicode 字符。
量词描述
n+匹配任何包含至少一个 n 的字符串。
n*匹配任何包含零个或多个 n 的字符串。
n?匹配任何包含零个或一个 n 的字符串。

使用误区

1.比较

在常规的比较中,数据类型是被忽略的,以下 if 条件语句返回 true:

var x = 10;
var y = "10";
if (x == y)

在严格的比较运算中,=== 为恒等计算符,同时检查表达式的值与类型,以下 if 条件语句返回 false:(switch 语句会使用恒等计算符(=)==进行比较:)

var x = 10;
var y = "10";
if (x === y)
2.浮点数

JavaScript 中的所有数据都是以 64 位浮点型数据(float) 来存储。

所有的编程语言,包括 JavaScript,对浮点型数据的精确度都很难确定:

var x = 0.1;
var y = 0.2;
var z = x + y            // z 的结果为 0.30000000000000004
if (z == 0.3)            // 返回 false

//为解决以上问题,可以用整数的乘除法来解决:

var z = (x * 10 + y * 10) / 10;     // z的结果为 0.3
3.JSON 与 JS 对象

JSON 是 JS 对象的字符串表示法。它使用文本表示一个 JS 对象的信息,(JSON)本质是一个字符串。如:

var obj = {a: 'Hello', b: 'World'}; //这是一个js对象,注意js对象的键名也是可以使用引号包裹的,这里的键名就不用引号包含
var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串

JSON(格式字符串)和JS对象互转(JSON.parse和 JSON.stringify)。

使用 JSON.parse() 方法从JSON字符串转换为JS对象:

var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //结果是 {a: 'Hello', b: 'World'}  一个对象
要实现从JS对象转换为JSON字符串,使用 JSON.stringify() 方法:

var json = JSON.stringify({a: 'Hello', b: 'World'}); //结果是 '{"a": "Hello", "b": "World"}'  一个JSON格式的字符串

JSON.parse() 就是字符串转 js 对象, JSON.stringify()就是 js 对象转字符串,
它们前提是要 json 格式才有意义。

JavaScript Promise

1.构造 Promise
new Promise(function (resolve, reject) {
    // 要做的事情...
});
2.使用resolve 和 reject

resolve 和 reject 都是函数,其中调用 resolve 代表一切正常,reject 是出现异常时所调用的:

  • resolve 和 reject 的作用域只有起始函数,不包括 then 以及其他序列;
  • resolve 和 reject 并不能够使起始函数停止运行,别忘了 return。
new Promise(function (resolve, reject) {
    var a = 0;
    var b = 1;
    if (b == 0) reject("Divide zero");
    else resolve(a / b);
}).then(function (value) {
    console.log("a / b = " + value);
}).catch(function (err) {
    console.log(err);
}).finally(function () {
    console.log("End");
});

这段程序执行结果是:

a / b = 0
End

Promise 类有 .then() .catch() 和 .finally() 三个方法,这三个方法的参数都是一个函数,.then() 可以将参数中的函数添加到当前 Promise 的正常执行序列,.catch() 则是设定 Promise 的异常处理序列,.finally() 是在 Promise 执行的最后一定会执行的序列。 .then() 传入的函数会按顺序依次执行,有任何异常都会直接跳到 catch 序列:

new Promise(function (resolve, reject) {
    console.log(1111);
    resolve(2222);
}).then(function (value) {
    console.log(value);
    return 3333;
}).then(function (value) {
    console.log(value);
    throw "An error";
}).catch(function (err) {
    console.log(err);
});

这段程序执行结果是:

1111
2222
3333
An error

JavaScript函数

1.函数参数

ES6自带参数

function myFunction(x, y = 10) {
    // y is 10 if not passed or undefined
    return x + y;
}
 
myFunction(0, 2) // 输出 2
myFunction(5); // 输出 15, y 参数的默认值

arguments对象

JavaScript 函数有个内置的对象 arguments 对象。
argument 对象包含了函数调用的参数数组,常称为隐式参数

x = sumAll(1, 123, 500, 115, 44, 88);
 
function sumAll() {
    var i, sum = 0;
    for (i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return sum;
}
2.函数调用

在浏览器中的页面对象是浏览器窗口(window 对象)。以上函数会自动变为 window 对象的函数。

myFunction() 和 window.myFunction() 是一样的:

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

myFunction(10, 2);           // myFunction(10, 2) 返回 20
window.myFunction(10, 2);    // window.myFunction(10, 2) 返回 20

全局对象

  • 当函数没有被自身的对象调用时 this 的值就会变成全局对象。
  • 在 web 浏览器中全局对象是浏览器窗口(window 对象)。
  • 该实例返回 this 的值是 window 对象:
function myFunction() {
    return this;
}
myFunction();                // 返回 window 对象

//对比对象种的this
var myObject = {
    firstName:"John",
    lastName: "Doe",
    fullName: function () {
        return this;
    }
}
myObject.fullName();          // 返回 [object Object] (所有者对象)

作为函数方法调用函数
call() 和 apply() 是预定义的函数方法。 两个方法可用于调用函数,两个方法的第一个参数必须是对象本身。

function myFunction(a, b) {
    return a * b;
}
myObject = myFunction.call(myObject, 10, 2);     // 返回 20

myArray = [10, 2];
myObject = myFunction.apply(myObject, myArray);  // 返回 20

两个方法都使用了对象本身作为第一个参数。 两者的区别在于第二个参数: apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。

  • 在 JavaScript 严格模式(strict mode)下, 在调用函数时第一个参数会成为 this 的值, 即使该参数不是一个对象。

  • 在 JavaScript 非严格模式(non-strict mode)下, 如果第一个参数的值是 null 或 undefined, 它将使用全局对象替代。

3.闭包
function add() {
    var counter = 0;
    return counter += 1;
}
 
add();
add();
add();
 
// 本意是想输出 3, 但事与愿违,输出的都是 1 !

比较于:

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();
 
add();
add();
add();
 
// 计数器为 3
  • 变量 add 指定了函数自我调用的返回字值。
  • 自我调用函数只执行一次。设置计数器为 0。并返回函数表达式。
  • add变量可以作为一个函数使用。非常棒的部分是它可以访问函数上一层作用域的计数器
  • 这个叫作 JavaScript 闭包。它使得函数拥有私有变量变成可能。
  • 计数器受匿名函数的作用域保护,只能通过 add 方法修改

DOM

1.HTMLCollection

getElementsByTagNamegetElementsByClassName 这两个方法查找多个 dom 元素,返回的是 htmlcollection 类型,是伪数组而不是真数组,故不能使用数组的方法。

我们可以使用数组原型配合 slice 方法,利用 call,apply,bind 方法将伪数组转为真数组。

var x=document.getElementById("main");
var y=x.getElementsByTagName("p");
console.log(y)//在控制台我们可以看到原型proto为htmlcollection,是伪数组
//伪数组转为真数组方法1
console.log(Array.prototype.slice.call(y))//在控制台我们可以看到原型proto为Array(0),是真数组

//伪数组转为真数组方法2
console.log(Array.prototype.slice.apply(y))//在控制台我们可以看到原型proto为Array(0),是真数组

//伪数组转为真数组方法3
console.log(Array.prototype.slice.bind(y)())//在控制台我们可以看到原型proto为Array(0),是真数组
2.NodeList

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

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

而大部分浏览器的 querySelectorAll() 返回 NodeList 对象。

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

HTMLCollection 与 NodeList 的区别

HTMLCollectionNodeList
HTML 元素的集合一个文档节点的集合
可以通过 name,id 或索引来获取只能通过索引来获取
/只有 NodeList 对象有包含属性节点和文本节点。

JavaScript对象

1.JavaScript prototype(原型对象)
function Person(first, last, age, eyecolor) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
  this.eyeColor = eyecolor;
}
 
var myFather = new Person("John", "Doe", 50, "blue");
Person.nationality = "English";
console.log(myFather.nationality) //undefined

对比于:使用prototype 属性(可添加属性及方法)

function Person(first, last, age, eyecolor) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
  this.eyeColor = eyecolor;
}
 
Person.prototype.nationality = "English";
Person.prototype.name = function() {
  return this.firstName + " " + this.lastName;
};
console.log(myFather.nationality) //English
2.Window
<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>


window.history.back()//返回上一页
window.history.forward()//前往下一页
window.history.go(1);  // go() 里面的参数表示跳转页面的个数 例如 history.go(1) 表示前进
window.history.go(-1);  // go() 里面的参数表示跳转页面的个数 例如 history.go(-1) 表示后退一个页面
window.history.go(0);  // go() 里面的参数为0,表示刷新页面

ES6-ES11指路:https://blog.csdn.net/lyyrhf/article/details/115338763

  • 43
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值