JavaScript基础复盘补缺

  • Post category:JavaScript

语法规范

JavaScript严格区分大小写,对空格、换行、缩进不敏感,建议语句结束加‘;’
JavaScript 会忽略多个空格。您可以向脚本添加空格,以增强可读性。
JavaScript 程序员倾向于使用以小写字母开头的驼峰大小写
firstName, lastName, masterCard, interCity
在运算符旁边( = + – * / )添加空格是个好习惯

JavaScript 允许您把一条语句换行为两行,但是,在字符串中间来换行是不对的,如果必须在字符串中换行,则必须在之间使用反斜杠

如果语句是不完整的,js会通过下一行读取。但如果完整再缓缓,会自动关闭语句,结尾自动添加;

JavaScript 会在行末关闭 return 语句,因为它本身就是一条完整的语句。

所以,绝不要对 return 语句进行换行。

提高JavaScript的性能

  1. 减少循环中的活动:语句或者赋值放到循环外会使得循环运行更快
  2. 减少DOM访问:DOM访问相较于其余JavaScript非常慢,建议如果多次访问就把它作为本地变量使用
  3. 缩减DOM规模:保持DOM中较少的元素,会提高页面加载速度,并加快渲染
  4. 减少不必要的变量
  5. 延迟JavaScript的加载,脚本放在页面底部,避免解析和渲染活动被阻塞

JavaScript异步加载:

引入js代码时(引入外链/内嵌),页面的下载和渲染都会暂停,等待脚本执行完后才执行,页面加载脚本文件会阻塞其他资源下载。对于外链式,对不需要提前执行的代码,将引入放在< body>标签底部。
HTML5新增两个可选属性:async,defer
async:用于异步加载,先下载文件,不阻塞其他代码执行,下载完成后再执行。
<script src='...' async></script>
defer:用于延后执行,即先下载文件,直到网页加载完成后再执行
<script src='...' defer></script>

eval() 的参数是一个字符串。

如果字符串表示的是表达式,eval() 会对表达式进行求值。如果参数表示一个或多个 JavaScript 语句,那么eval() 就会执行这些语句。不需要用 eval() 来执行一个算术表达式:因为 JavaScript 可以自动为算术表达式求值。返回字符串中代码的返回值。如果返回值为空,则返回 undefined。

如果你以字符串的形式构造了算术表达式,那么可以在后面用 eval()对它求值。例如,假设你有一个变量 x,您可以通过将表达式的字符串值(例如 3 * x + 2)赋值给一个变量,然后在你的代码后面的其他地方调用 eval(),来推迟涉及 x 的表达式的求值。

如果 eval() 的参数不是字符串, eval() 会将参数原封不动地返回。在下面的例子中,String 构造器被指定,而 eval() 返回了 String 对象而不是执行字符串。
eval(new String("2 + 2")); // 返回了包含"2 + 2"的字符串对象
eval("2 + 2"); // returns 4

外部 JavaScript 的优势

在外部文件中放置脚本有如下优势:

分离了 HTML 和代码
使 HTML 和 JavaScript 更易于阅读和维护
已缓存的 JavaScript 文件可加速页面加载
如需向一张页面添加多个外部脚本文件 – 请使用多个 script 标签

JavaScript的位置

<head> 或 <body> 中的 JavaScript
您能够在 HTML 文档中放置任意数量的脚本。

脚本可被放置与 HTML 页面的 <body><head> 部分中,或兼而有之。
把脚本置于 <body> 元素的底部,可改善显示速度,因为脚本编译会拖慢显示。

HTML路径

路径 描述
<img src="picture.jpg"> picture.jpg 位于与当前网页相同的文件夹
<img src="images/picture.jpg"> picture.jpg 位于当前文件夹的 images 文件夹中
<img src="/images/picture.jpg"> picture.jpg 当前站点根目录的 images 文件夹中
<img src="../picture.jpg"> picture.jpg 位于当前文件夹的上一级文件夹中

文件路径描述了网站文件夹结构中某个文件的位置。文件路径会在链接外部文件时被用到。
绝对文件路径是指向一个因特网文件的完整 URL,相对路径指向了相对于当前页面的文件。

JavaScript 显示方案

JavaScript 能够以不同方式“显示”数据: 描述 补充
使用 document.write() 写入 HTML 输出 出于测试目的,使用 document.write() 比较方便。
输出内容位置与script标签插入的位置有关、
document.write() 方法仅用于测试。
在 HTML 文档完全加载后使用 document.write()删除所有已有的 HTML
使用 innerHTML 写入 HTML 元素 innerHTML 属性定义 HTML 内容
使用 console.log() 写入浏览器控制台 在浏览器中,您可使用 console.log() 方法来显示数据。
使用 window.alert() 写入警告框 用警告框来显示数据,打开页面弹出警告框

JavaScript 关键词

语句常常通过某个关键词来标识需要执行的 JavaScript 动作。

下面的表格列出了一部分将在教程中学到的关键词:

关键词 描述
break 终止 switch 或循环。
continue 跳出循环并在顶端开始。
debugger 停止执行 JavaScript,并调用调试函数(如果可用)。
return 退出函数
try … catch 对语句块实现错误处理。
var var 关键词告知浏览器创建新的变量

JavaScript 值

JavaScript 语句定义两种类型的值:混合值和变量值。

混合值被称为字面量(literal)。变量值被称为变量。

字符串是文本,由双引号或单引号包围,加了引号的就是文本包括数字
使用变量不要加”“

文本:"你好","12",
数字:12

JavaScript 变量

在编程语言中,变量用于存储数据值。

JavaScript 使用 var 关键词来声明变量。

= 号用于为变量赋值

var a = "hello"
var b =17

JavaScript 标识符
所有 JavaScript 变量必须以唯一的名称的标识。这些唯一的名称称为标识符。

标识符可以是短名称(比如 x 和 y),或者更具描述性的名称(age、sum、totalVolume)。

构造变量名称(唯一标识符)的通用规则是:

名称可包含字母、数字、下划线和美元符号
名称必须以字母开头
名称也可以 $ 和 _ 开头(但是在本教程中我们不会这么做)
名称对大小写敏感(y 和 Y 是不同的变量)
保留字(比如 JavaScript 的关键词)无法用作变量名称
提示:JavaScript 标识符对大小写敏感

声明变量

var a;//声明变量,不赋值的话,a=undefined
a=10;//给变量赋值

/*一条语句,多个变量
您可以在一条语句中声明许多变量。
声明可横跨多行*/

var person = "Bill Gates",
carName = "porsche",
price = 15000;

以 var 作为语句的开头,并以逗号分隔变量

JavaScript 表达式

表达式是值、变量和运算符的组合,结果为值(数字,字符串),也可以包含变量

12 + 29
a*2
"Allerge" + "Xia"

注释

//单行注释

/*
多行注释
被称为注释块
*/

应用:解释代码;阻止代码执行
使用单行注释最为常见。

提示:注释块常用于官方声明。

JavaScript作用域

ES2015前只有全局和函数(局部)

ES2015之后有全局、函数、块级作用域

JavaScript 变量的有效期

JavaScript 变量的有效期始于其被创建时。

局部变量会在函数完成时被删除。

全局变量会在您关闭页面是被删除。

作用域 描述 应用
全局作用域 全局 (在函数之外)声明的变量拥有 全局作用域 全局变量可以在 JavaScript 程序中的任何位置访问
函数作用域 局部 (函数内)声明的变量拥有函数作用域 局部变量只能访问函数内部的变量
块级作用域 在块{} 内声明的变量无法从块外访问 函数、循环的{}
var carName = "porsche";

// 此处的代码可以使用 carName

function myFunction() {
  // 此处的代码也可以使用 carName
	var busName = "finghter"
	//此处可以使用busName
}
//此处不可以使用busName

var,let,const关键字

不通过关键词 var 创建的变量总是全局的,即使它们在函数中创建。

var let const 补充
声明的变量没有块作用域 声明拥有块作用域的变量 通过 const 定义的变量与 let 变量类似,但不能重新赋值
在块{} 内声明的变量可以从块之外进行访问 在块{} 内声明的变量无法从块外访问 const 变量必须在声明时赋值
使用var关键词在块中重新声明变量
将重新声明块外的变量
使用let关键词在块中重新声明变量
不会重新声明块外的变量
const定义的不是常数,定义了对值的常量引用
我们不能更改常量原始值,
但我们可以更改常量对象的属性,可以更改常量数组的元素
通过 var 关键词定义的全局变量属于 window 对象 通过 let关键词定义的全局变量不属于 window 对象,
不能通过window.let声明的变量
const可以改变数组、对象内的值,但不能重新赋值
允许在程序的任何位置使用 var重新声明 相同的作用域,或在相同的块中,通过 let 重新声明一个 var 变量是不允许的
通过 var 重新声明一个 let 变量是不允许的
不同的作用域或块中,通过let重新声明变量是允许的
在同一作用域或块中,不允许将已有的 var 或 let或const 变量
重新声明或重新赋值给 const
在另外的作用域或块中重新声明 const 是允许的
通过 var 声明的变量提升到顶端
可以在声明前使用变量
通过 let 定义的变量不会被提升到顶端
在声明 let 变量之前就使用它会导致 ReferenceError。
变量从块的开头一直处于“暂时死区”,直到声明为止
通过const定义的变量不会被提升到顶端
const变量不能在声明之前使用

JavaScript 只提升声明,而非初始化。

重新声明变量

使用 var 关键字重新声明变量会带来问题。

使用 let 关键字重新声明变量可以解决这个问题。

在块中重新声明变量不会重新声明块外的变量

var x = 10;
// 此处 x 为 10
{ 
  let x = 6;
  // 此处 x 为 6
}
// 此处 x 为 10
var x = 10;
// 此处 x 为 10
{ 
  var x = 6;
  // 此处 x 为 6
}
// 此处 x 为 6

如果在块外声明声明,那么 var 和 let 也很相似。它们都拥有全局作用域

在函数内声明变量时,使用 var 和 let 很相似。它们都有函数作用域

幂运算符

取幂运算符(**)将第一个操作数提升到第二个操作数的幂

var x = 5;
var z = x ** 2;          // 结果是 25

x ** y 产生的结果与 Math.pow(x,y) 相同:

var x = 5;
var z = Math.pow(x,2);   // 结果是 25

JavaScript 从左向右计算表达式。不同的次序会产生不同的结果

var x = 911 + 7 + "Porsche";//918Porsche
var x = "Porsche" + 911 + 7;//Porsche9117

Undefined 与 Null 的区别

Undefinednull 的值相等,但类型不相等:

typeof undefined              // undefined
typeof null                   // object
null === undefined            // false
null == undefined             // true

空值

空值与 undefined 不是一回事。

空的字符串变量既有值也有类型。

var car = "";                // 值是 "",类型是 "string"

typeof 运算符

您可使用 JavaScript 的 typeof 来确定 JavaScript 变量的类型:

typeof 运算符返回变量或表达式的类型

原始数据值是一种没有额外属性和方法的单一简单数据值。

typeof 运算符可返回以下原始类型之一:

  • string
  • number
  • boolean
  • undefined

复杂数据

typeof 运算符可返回以下两种类型之一:

  • function
  • object

typeof 运算符把对象、数组或 null 返回 object

typeof 运算符不会把函数返回 object

constructor属性

constructor 属性返回所有 JavaScript 变量的构造函数。

有 6 种类型的对象:

  • Object
  • Date
  • Array
  • String
  • Number
  • Boolean
"Bill".constructor                // 返回 function String()  {[native code]}
(3.14).constructor                // 返回 function Number()  {[native code]}
false.constructor                 // 返回 function Boolean() {[native code]}
[1,2,3,4].constructor             // 返回 function Array()   {[native code]}
{name:'Bill',age:19}.constructor  // 返回 function Object()  {[native code]}
new Date().constructor            // 返回 function Date()    {[native code]}
function () {}.constructor        // 返回 function Function(){[native code]}

JavaScript 函数

JavaScript 函数是被设计为执行特定任务的代码块。

JavaScript 函数会在某代码调用它时被执行。

函数

声明函数

函数只要定义一次代码,就可以多次使用,多次向同一函数传递不同参数得到不同的结果

function name(参数 1, 参数 2, 参数 3) {
    要执行的代码
}

匿名函数

hello = function() {
  return "Hello World!";
}

ECMAScript 的函数Function对象( 类)实际上是功能完整的对象

使用Function对象( 类)可以表示开发者定义的任何函数

var function_name = new Function(arg1, arg2, ..., argN, function_body)

前面是参数,最后是函数逻辑主体

函数名只是指向函数对象的引用值

尽管可以使用 Function 构造函数创建函数,但最好不要使用它,因为用它定义函数比用传统方式要慢得多。不过,所有函数都应看作 Function 类的实例。

箭头函数

ES6 中引入了箭头函数。

箭头函数允许我们编写更短的函数

hello = () => "Hello World!";

如果函数只有一个语句,并且该语句返回一个值,则可以去掉括号和 return 关键字

如果只有一个参数,您也可以略过括号

hello = val => "Hello " + val;

函数属于引用类型,所以它们也有属性和方法。

length属性,属性 length 只是为查看默认情况下预期的参数个数提供了一种简便方式。

与所有对象共享的 valueOf() 方法和 toString() 方法,返回的都是函数的源代码

function doAdd(iNum) {
  alert(iNum + 10);
}
function sayHi() {
  alert("Hi");
}
alert(doAdd.length);	//输出 "1"
alert(sayHi.length);//输出"0"
document.write(sayHi.toString());//function sayHi(){alert("Hi");}

函数调用

用( )调用函数,没有()的函数返回的是定义的函数

函数中的代码将在其他代码调用该函数时执行:

  • 当事件发生时(当用户点击按钮时)
  • 当 JavaScript 代码调用时
  • 自动的(自调用)

call(参数1,参数2,,)& apply(参数1,[参数2,…])

call() 方法是预定义的 JavaScript 方法。

它可以用来调用所有者对象作为参数的方法。

通过 call(),您能够使用属于另一个对象的方法。

apply() 方法与 call() 方法非常相似

var person = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
var person1 = {
    firstName: "Bill",
    lastName: "Gates",
}
person.fullName.apply(person1);//person1调用person的fullName方法
应用:
手写bind
 Function.prototype.myBind_1=function(){
    let outContext=arguments[0] // 取上下文
    let outArgs=Array.from(arguments).slice(1) // 取外部入参
    const outThis=this// 存外部this
    let cb=function(){
        const  inArgs=Array.from(arguments)// 取内部入参
        return outThis.apply(outContext,outArgs.concat(inArgs)) // 改变指向,合并函数入参  
	}  
	return	cb// 返回创建函数}
数组上模拟max方法

Math.min()Math.max() 可用于查找参数列表中的最低或最高值

Math.max(1,2,3)

数组上没有max方法,应用Math.max()方法,第一个参数无关紧要,可以写为(null,undefined,Math,”,0,…目前测试任何值没有报错),若不写则保错

Math.max.apply(null, [1,2,3]); 

函数返回

当 JavaScript 到达 return 语句,函数将停止执行。

函数在执行过 return 语句后立即停止代码。因此,return 语句后的代码都不会被执行。

如果函数被某条语句调用,JavaScript 将在调用语句之后“返回”执行代码。

函数通常会计算出 返回值 。这个返回值会返回给调用者:

function myFunction(a, b) {
    return a * b;                // 函数返回 a 和 b 的乘积
}
document.getElementById("demo").innerHTML = myFunction;
//没有(),function myFunction(a, b) { return a * b; // 函数返回 a 和 b 的乘积 }
document.getElementById("de").innerHTML = myFunction(1,2);
//有(),2

变量

函数可以访问函数内的变量(局部函数),也可以访问函数外面的变量(全局变量)

在网页中,全局变量属于 window 对象。

全局变量能够被页面中(以及窗口中)的所有脚本使用和修改,因为全部变量可以在任何位置

局部变量只能用于其被定义的函数内部。对于其他函数和脚本代码来说它是不可见的。

拥有相同名称的全局变量和局部变量是不同的变量。修改一个,不会改变其他。

不通过关键词 var 创建的变量总是全局的,即使它们在函数中创建。

变量的生命周期

全局变量活得和您的应用程序(窗口、网页)一样久。

局部变量活得不长。它们在函数调用时创建,在函数完成后被删除。

局部变量

在 JavaScript 函数中声明的变量,会成为函数的 局部变量

局部变量只能在函数内访问。通过return传出则可以使用,若跟全局变量重名,则释放原来的变量

由于局部变量只能被其函数识别,因此可以在不同函数中使用相同名称的变量。

局部变量在函数开始时创建,在函数完成时被删除

arguments 对象

在函数代码中,使用特殊对象 arguments,开发者 无需明确指出参数名 ,就能访问它们。arguments中包含所以参数

应用:

arguments[0],伪数组中索引号为0的元素

arguments.length,检测函数的参数个数

模拟函数重载

用 arguments 对象判断传递给函数的参数个数,即可模拟函数重载,即通过arguments.length判断个数,arguments[?]对不同位置的参数以另种进行重新加载

function doAdd() {
  if(arguments.length == 1) {
    alert(arguments[0] + 5);
  } else if(arguments.length == 2) {
    alert(arguments[0] + arguments[1]);
  }
}

doAdd(10);	//输出 "15"
doAdd(40, 20);	//输出 "60"

闭包

函数可以使用函数之外定义的变量

简单闭包

var sMessage = "hello world";

function sayHelloWorld() {
  alert(sMessage);//执行函数时使用全局变量
}

sayHelloWorld();

复杂闭包

在一个函数中定义另一个函数会使闭包变得更加复杂

var iBaseNum = 10;

function addNum(iNum1, iNum2) {
//addNum输入两个参数iNum1,iNum2
  function doAdd() {
//doAdd函数无输入参数
    return iNum1 + iNum2 + iBaseNum;
  }
  return doAdd();
}

函数 addNum() 包括函数 doAdd() (闭包)。

内部函数是一个闭包,它将获取外部函数的参数 iNum1 和 iNum2 以及全局变量 iBaseNum 的值。

addNum() 的最后一步调用了 doAdd(),把两个参数和全局变量相加,并返回它们的和。

这里要掌握的重要概念是,doAdd() 函数根本不接受参数,它使用的值是从执行环境中获取的。

闭包是 ECMAScript 中非常强大多用的一部分,可用于执行复杂的计算。

自调用函数

匿名的自调用函数

函数表达式可以作为“自调用”。

自调用表达式是自动被调用(开始)的,在不进行调用的情况下。

函数表达式会自动执行,假如表达式后面跟着 ()

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

嵌套函数

所有函数都有权访问全局作用域。

事实上,在 JavaScript 中,所有函数都有权访问它们“上面”的作用域。

JavaScript 支持嵌套函数。嵌套函数可以访问其上的作用域

function add() {
    var counter = 0;
    function plus() {counter += 1;}
    plus();   
    return counter; 
}

add是一个自调用函数,第一个add(),首先声明并初始化counter,返回一个函数表达式 add=function () {return counter += 1;},add()调用返回值counter=1做全局变量,再add(),add(),最后返回值为3

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();
add=function () {return counter += 1;}
}
add();
counter = 1;
add(); 
counter = 2;
add();
counter = 3;

对象

对象包含属性和方法,以键值对的形式来书写

方法是作为属性来存储的函数,是在对象上执行的 动作

var obj ={   
  name:"xiatian",  
  skill:function(){
        var rate =18;  
         return rate;
	 }
}

访问对象属性的两种方式:

obj.name
obj['name']

访问对象方法的方式:

obj.skill()

如果访问对象的方法时没有加(),则返回的是函数的定义

显示 JavaScript 对象

一些常见解决方案是:

  • 按名称显示对象属性
  • 循环显示对象属性
  • 使用 Object.values() 显示对象,返回属性值数组
  • 使用 JSON.stringify() 显示对象,进行字符串化,返回JSON数据格式
const person = {
  name: "Bill",
  age: 19,
  city: "Seattle"
};
var name =person.name;//'Bill'
for(i in person){
	console.log(i,person[i]);//i为对象属性,person[i]为属性值
}
var human = Object.values(person);//['Bill', 19, 'Seattle']

var people = JSON.stringify(person);//'{"name":"Bill","age":19,"city":"Seattle"}'
console.log(human,people);

JavaScript 访问器(Getter 和 Setter)

ECMAScript 5 (2009) 引入了 Getter 和 Setter。

Getter 和 Setter 允许您定义对象访问器(被计算的属性)。

Getter (get关键词)获取属性值

get 属性名(){ //}

区别于函数,get获取数据时,对象.属性名;对象函数获取数据时,对象.方法名()

Object.defineProperty()

Object.defineProperty() 方法也可用于添加 Getter 和 Setter

Object.defineProperty(对象,方法,函数)

// 定义对象
var obj = {counter : 0};
Object.defineProperty(obj, "reset", {
  get : function () {this.counter = 0;}
});
var obj = {
  counter : 0,
  get reset() {
    this.counter = 0;
  }
}

Setter(set关键词)设置属性值

为什么使用 Getter 和 Setter?

  • 它提供了更简洁的语法
  • 它允许属性和方法的语法相同
  • 它可以确保更好的数据质量
  • 有利于后台工作

对象构造器

用大写字母为构造函数命名

function Person(first, last, age, eye) {
    this.firstName = first;
    this.lastName = last;
    this.age = age;
    this.eyeColor = eye;
    this.name = function(){
	return this.firstName + this.lastName;
	}
}

在上面的例子中,函数 Person() 就是对象构造器函数。

通过 new 关键词调用构造器函数可以创建相同类型的对象:

var myFather = new Person("Bill", "Gates", 62, "blue");
var myMother = new Person("Steve", "Jobs", 56, "green");

在构造器函数中,this 是没有值的。它是新对象的替代物。 当一个新对象被创建时,this 的值会成为这个新对象。

  • 为对象添加属性myFather.gender = ‘man’
  • 为对象添加方法 myFather.sayHi= function()
  • 为构造器添加属性、方法都需要直接加到构造器函数function Person(){}上

内建 JavaScript 构造器

JavaScript 提供用于原始对象的构造器:

var x1 = new Object();    // 一个新的 Object 对象
var x2 = new String();    // 一个新的 String 对象
var x3 = new Number();    // 一个新的 Number 对象
var x4 = new Boolean();   // 一个新的 Boolean 对象
var x5 = new Array();     // 一个新的 Array 对象
var x6 = new RegExp();    // 一个新的 RegExp 对象
var x7 = new Function();  // 一个新的 Function 对象
var x8 = new Date();      // 一个新的 Date 对象

JavaScript 提供原始数据类型字符串、数字和布尔的对象版本,优点是快

var x1 = {};            // 新对象
var x2 = "";            // 新的原始字符串
var x3 = 0;             // 新的原始数值
var x4 = false;         // 新的原始逻辑值
var x5 = [];            // 新的数组对象
var x6 = /()/           // 新的正则表达式对象
var x7 = function(){};  // 新的函数对象

对象原型

所有 JavaScript 对象都从原型继承属性和方法

JavaScript prototype 属性允许您为对象构造器添加新属性、新方法

Person.prototype.name = function(){return this.firstName+this.lastName}

ECMAScript 5 (2009) 向 JavaScript 添加了许多新的对象方法。

管理对象

// 以现有对象为原型创建对象
Object.create()

// 添加或更改对象属性
Object.defineProperty(object对象, property属性, descriptor)

// 添加或更改对象属性
Object.defineProperties(object, descriptors)

// 访问属性
Object.getOwnPropertyDescriptor(object, property)

// 以数组返回所有属性
Object.getOwnPropertyNames(object)

// 访问原型
Object.getPrototypeOf(object)

// 以数组返回可枚举属性
Object.keys(object)

Object.defineProperty():添加属性,添加Getter和Setter

更改元数据

ES5 允许更改以下属性元数据:descriptors

writable : true      // 属性值可更改
enumerable : true    // 属性可枚举
configurable : true  // 属性可重新配置

this 关键词

在函数定义中,this 引用该函数的“拥有者”。

this.firstName,this 指的是“拥有” fullName 函数的 person 对象

换言之, 的意思是 this 对象的 firstName 属性。

JavaScript this 关键词指的是它所属的对象。

在常规函数中,关键字 this 表示调用该函数的对象,可以是窗口、文档、按钮或其他任何东西

它拥有不同的值,具体取决于它的使用位置:

  • 在对象方法中,this 指的是拥有该方法的对象

  • 单独的情况下,this 指的是全局对象(严格模式下也是)。

  • 在函数中,函数的拥有者默认绑定 thisthis 指的是全局对象。严格模式下,this 是 undefined。

  • 在事件中,this 指的是接收事件的元素

  • 对于箭头函数,this 关键字始终表示定义箭头函数的对象,window 对象是函数的“所有者”。用了箭头函数,则 this 表示函数的拥有者

    <script>
    var x = this;//全局对象
    var obj = {
    age:18;
    fullName : function() {
    return this.firstName + " " + this.lastName;//this指向obj对象
    return this;
    }
    function myFunction() {
    return this;//全局对象
    }
    </script>
    <body>
    <button onclick="this.style.display='none'">单击来删除我!</button>//this指的是接收事件的button
    

显式函数绑定 call()apply()

call()apply() 方法是预定义的 JavaScript 方法。

它们都可以用于将另一个对象作为参数调用对象方法。

JavaScript 事件

HTML 事件是发生在 HTML 元素上的“事情”。

当在 HTML 页面中使用 JavaScript 时,JavaScript 能够“应对”这些事件。

通常,当事件发生时,用户会希望做某件事。JavaScript 允许您在事件被侦测到时执行代码。

通过 JavaScript 代码 ,HTML 允许您向 HTML 元素添加事件处理程序

常见的 HTML 事件

下面是一些常见的 HTML 事件:

事件 描述
onchange HTML 元素已被改变
onclick 用户点击了 HTML 元素
onmouseover 用户把鼠标移动到 HTML 元素上
onmouseout 用户把鼠标移开 HTML 元素
onkeydown 用户按下键盘按键
onload 浏览器已经完成页面加载

HTML DOM 事件允许 JavaScript 在 HTML 文档中的元素上注册不同的事件处理程序。

事件通常与函数结合使用,在事件发生之前函数不会被执行(例如当用户单击按钮时)。

JavaScript 能够做什么?

事件处理程序可用于处理、验证用户输入、用户动作和浏览器动作

  • 每当页面加载时应该做的事情
  • 当页面被关闭时应该做的事情
  • 当用户点击按钮时应该被执行的动作
  • 当用户输入数据时应该被验证的内容
  • 等等

让 JavaScript 处理事件的不同方法有很多:

  • HTML 事件属性可执行 JavaScript 代码
  • HTML 事件属性能够调用 JavaScript 函数
  • 您能够向 HTML 元素分配自己的事件处理函数
  • 您能够阻止事件被发送或被处理

转义序列:

使用 \ 转义字符,反斜杠转义字符把特殊字符转换为字符串字符

代码 结果
\b 退格键
\f 换页
\n 新行
\r 回车
\t 水平制表符
\v 垂直制表符

字符串方法

方法 说明
length 属性返回字符串的长度
ECMAScript 5 (2009) 允许对字符串的属性访问 [ ] 使用属性访问有点不太靠谱
replace() 用另一个值替换在字符串中指定的值
不改变字符串,返回的是新字符串 ,只替换首个匹配,对大小写敏感
toUpperCase() 把字符串转换为大写
toLowerCase() 把字符串转换为小写
concat() 方法可用于代替加运算符
trim() 方法删除字符串两端的空白符
split() 将字符串转换为数组
省略分隔符,被返回的数组将包含 index [0] 中的整个字符串
分隔符是 “”,被返回的数组将是间隔单个字符的数组

字符串搜索

方法 描述
indexOf()(从前往后) 方法返回字符串中指定文本首次出现的索引(位置)
lastIndexOf()(从后向前) 方法返回指定文本在字符串中最后一次出现的索引
search() 方法搜索特定值的字符串,并返回匹配的位置
match() 方法根据正则表达式在字符串中搜索匹配项,并将匹配项作为 Array 对象返回

补充:

如果未找到文本,indexOf()和 lastIndexOf() 均返回 -1
indexOf() 方法无法设置更强大的搜索值(正则表达式)
两种方法都接受作为检索起始位置的第二个参数。

var str = "The full name of China is the People's Republic of China."
var pos = str.lastIndexOf("China", 50);//

indexOf()search(),是 相等的

这两种方法是不相等的。区别在于:

  • search() 方法无法设置第二个开始位置参数。
  • indexOf() 方法无法设置更强大的搜索值(正则表达式)。
方法
如果字符串包含指定值,includes() 方法返回 true includes()
如果字符串以指定值开头,则 startsWith() 方法返回 true,否则返回 false startsWith()
如果字符串以指定值结尾,则 endsWith() 方法返回 true,否则返回 false endsWith()
test() 是一个正则表达式方法。它通过模式来搜索字符串,然后根据结果返回 true 或 false test())
exec() 方法是一个正则表达式方法。它通过指定的模式(pattern)搜索字符串,并返回已找到的文本。
如果未找到匹配,则返回 null。
exec())

提取部分字符串

有三种提取部分字符串的方法:

方法 描述 区别
slice(start , end ) 提取字符串的某个部分并在新字符串中返回被提取的部分。
如果某个参数为负,则从字符串的结尾开始计数
substring(start , end ) 该方法设置两个参数:起始索引(开始位置),终止索引(结束位置)
如果省略第二个参数,则该方法将裁剪字符串的剩余部分
substring() 无法接受负的索引
substr(start , length ) substr() 类似于 slice() 不同之处在于第二个参数规定被提取部分的长度
charAt(position) 方法返回字符串中指定下标(位置)的字符串
charCodeAt(position ) 方法返回字符串中指定索引的字符 unicode 编码

IE 8 不支持 String.trim()。您可以使用 replace 方案把 trim 函数添加到 JavaScript String.prototype:

if (!String.prototype.trim) {
  String.prototype.trim = function () {
    return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  };
};
var str = "     Hello World!    ";
alert(str.trim());

数字方法

toString() 方法

toString() 以字符串返回数值。

所有数字方法可用于任意类型的数字(字面量、变量或表达式)

toFixed() 方法

toFixed() 返回字符串值,它包含了指定位数小数的数字

toPrecision() 方法

toPrecision() 返回字符串值,它包含了指定长度的数字

valueOf() 方法

valueOf() 以数值返回数值

var x = 123;
x.valueOf();            // 从变量 x 返回 123
(123).valueOf();        // 从文本 123 返回 123
(100 + 23).valueOf();   // 从表达式 100 + 23 返回 123

全局方法

方法 描述
Number() 返回数字,由其参数转换而来。把 JavaScript 变量转换为数值
parseFloat() 解析其参数并返回浮点数。允许空格。只返回首个数字
parseInt() 解析其参数并返回整数。允许空格。只返回首个数字

如果无法转换为数值,则返回 NaN

数值属性

var x = Number.数值属性

数字属性不可用于变量

属性 描述
MAX_VALUE 返回 JavaScript 中可能的最大数。
MIN_VALUE 返回 JavaScript 中可能的最小数。
NEGATIVE_INFINITY 表示负的无穷大(溢出返回)。
NaN 表示非数字值(”Not-a-Number”)。
POSITIVE_INFINITY 表示无穷大(溢出返回)。

遍历

遍历数组的最安全方法是使用 “for” 循环

Array.forEach() 函数

参数:项目值;项目索引;数组本身

forEach() 方法为每个数组元素调用一次函数(回调函数)。

const numbers = [45, 4, 9, 16, 25];

let txt = "";
numbers.forEach(myFunction);

function myFunction(value, index, array) {
  txt += value;
}

两种重要的 for 循环

for …of

JavaScript for of 语句循环遍历可迭代对象的值。

它允许您循环遍历可迭代的数据结构,例如数组、字符串、映射、节点列表等

for (let value of array) {
  // do something with value
}

for …in

数组、对象、字符串

如果索引顺序很重要,请不要在数组上使用 for in

索引顺序依赖于实现,可能不会按照您期望的顺序访问数组值。

当顺序很重要时,最好使用 for 循环、for of 循环或 Array.forEach()

for (let property in object) {
  // do something with object property
}

Array.map()

参数:项目值;项目索引;数组本身

通过对每个数组元素执行函数来创建新数组

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

function myFunction(value, index, array) {
  return value * 2;
}

Array.filter()

参数:项目值;项目索引;数组本身

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

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

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

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

Array.reduce()

reduce() 方法在每个数组元素上运行函数,以生成(减少它)单个值。reduce() 方法不会减少原始数组。

参数:总数(初始值/先前返回的值);项目值;项目索引;数组本身

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

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

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

Array.every()

参数:项目值;项目索引;数组本身

every() 方法检查所有数组值是否通过测试

检测所以数值大于18

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

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

Array.find()

参数:项目值;项目索引;数组本身

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

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

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

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

Array.lastIndexOf(item,start)

从数组结尾开始搜索,返回索引号

Array.indexOf(item,start)

indexOf() 方法在数组中搜索元素值并返回其位置

参数:item搜索元素,start开始搜索的位置

Array.findIndex()

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

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

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

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

Array.every()

参数:项目值;项目索引;数组本身

every() 方法检查所有数组值是否通过测试。

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

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

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

Array.some()

参数:项目值;项目索引;数组本身

some() 方法检查某些数组值是否通过了测试。

检查某些数组值是否大于 18:

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

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

数组和对象的区别

在 JavaScript 中,数组使用 数字索引

在 JavaScript 中,对象使用 命名索引

数组是特殊类型的对象,具有数字索引

识别数组

  • typeof 运算符返回 “object”,因为 JavaScript 数组属于对象
  • ECMAScript 5 定义了新方法 Array.isArray(),返回布尔值
  • 创建您自己的 isArray() 函数以解决此问题:
  • function isArray(x) {
    return x.constructor.toString().indexOf("Array") > -1;
    //假如对象原型包含单词 "Array" 则返回 true
    }
    
  • 假如对象由给定的构造器创建,则 instanceof 运算符返回 true
  • var fruits = ["Banana", "Orange", "Apple", "Mango"];
    
    fruits instanceof Array     // 返回 true
    

数组方法

toString():JavaScript 方法 toString() 把数组转换为数组值(逗号分隔)的字符串

join() :方法也可将所有数组元素结合为一个字符串。它的行为类似 toString(),但是您还可以规定分隔符

delete(): 以使用 JavaScript delete 运算符来删除会在数组留下未定义的空洞undefined

splice(index,delete,add) :方法可用于向数组添加新项、删除元素,返回一个包含已删除项的数组不留空洞

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2, 2, "Lemon", "Kiwi");
//在索引号2的位置删除两个元素,添加两个元素,返回删除的两个数组

concat(): 方法通过合并(连接)现有数组来创建一个新数组

slice(start[,end]) 方法从start开始用数组的某个片段切出新数组

sort() 方法以字母顺序对数组进行排序,

比值函数:数字按照字符串来排序

sort(function(a, b){return a - b});//从小到大
sort(function(a, b){return b - a});//从大到小
var cars = [
{type:"Volvo", year:2016},
{type:"Saab", year:2001},
{type:"BMW", year:2010}
];
cars.sort(function(a, b){return a.year - b.year});//按照year从小到大的顺序

reverse() 方法反转数组中的元素。可以用它以降序对数组进行排序

Class 类 方法

类方法的创建,类中的语法必须以“严格模式”编写。

ECMAScript 2015,也称为 ES6,引入了 JavaScript 类。

JavaScript 类是 JavaScript 对象的模板。

语法

类方法与对象方法相同。

请使用关键字 class 创建类。

请始终添加 constructor() 方法。

然后添加任意数量的方法。

class ClassName {
  constructor() { ... }
  method_1() { ... }
  method_2() { ... }
  method_3() { ... }
}

类继承

如需创建类继承,请使用 extends 关键字。

使用类继承创建的类继承了另一个类的所有方法

super() 方法引用父类。

通过在 constructor 方法中调用 super() 方法,我们调用了父级的 constructor 方法,获得了父级的属性和方法的访问权限。

继承对于代码可重用性很有用:在创建新类时重用现有类的属性和方法

class Car {
  constructor(brand) {
    this.carname = brand;
  }
  present() {
    return 'I have a ' + this.carname;
  }
}

class Model extends Car {
  constructor(brand, mod) {
    super(brand);
    this.model = mod;
  }
  show() {
    return this.present() + ', it is a ' + this.model;
  }
}

let myCar = new Model("Ford", "Mustang");
document.getElementById("demo").innerHTML = myCar.show();

类允许使用 getter 和 setter。

为您的属性使用 getter 和 setter 很聪明,特别是如果您想在返回它们之前或在设置它们之前对值做一些特殊的事情。

如需在类中添加 getter 和 setter,请使用 getset 关键字

可以使用下划线字符将 getter/setter 与实际属性分开:

class Car {
  constructor(brand) {
    this._carname = brand;
  }
  get carname() {
    return this._carname;
  }
  set carname(x) {
    this._carname = x;
  }
}

let myCar = new Car("Ford");

document.getElementById("demo").innerHTML = myCar.carname;

类声明不会被提升:必须先声明类才能使用

与函数和其他 JavaScript 声明不同,类声明不会被提升。

这意味着您必须先声明类,然后才能使用它

//您还不能使用该类。
//myCar = new Car("Ford")
//This would raise an error.

class Car {
  constructor(brand) {
    this.carname = brand;
  }
}

//现在您可以使用该类:
let myCar = new Car("Ford")

对于其他声明,如函数,在声明之前尝试使用它时不会出错,因为 JavaScript 声明的默认行为是提升(将声明移到顶部)

static 类方法

static 类方法是在类本身上定义的。

您不能在对象上调用 static 方法,只能在对象类上调用。

class Car {
  constructor(name) {
    this.name = name;
  }
  static hello() {
    return "Hello!!";
  }
  static hi(x) {
    return "Hello!!"+x.name;
 
  }
}

let myCar = new Car("Ford");

// 您可以在 Car 类上调用 'hello()' :
document.getElementById("demo").innerHTML = Car.hello();//Hello
document.getElementById("demo").innerHTML = Car.hi(myCar);//Hello!!Ford
// 但不能在 Car 对象上调用:
// document.getElementById("demo").innerHTML = myCar.hello();
// 此举将引发错误

要在 static 方法中使用 myCar 对象,可以将其作为参数发送

Constructor 方法

构造方法是一种特殊的方法:

  • 它必须拥有确切名称的“构造函数”
  • 创建新对象时自动执行
  • 用于初始化对象属性
  • 如果未定义构造函数方法,JavaScript 会添加空的构造函数方法。
class Car {
//constructor输入参数
  constructor(name, year) {
    this.name = name;
    this.year = year;
  }
//方法函数
  age(x) {
    return x - this.year;
  }
}

let date = new Date();
let year = date.getFullYear();

JSON

JSON 是存储和传输数据的格式。轻量级数据交换格式

JSON 经常在数据从服务器发送到网页时使用

JSON 的通常用法是从 web 服务器读取数据,然后在网页中显示数据

我们能够把任何 JavaScript 对象转换为 JSON,然后将 JSON 发送到服务器。

JSON 格式是纯文本。读取和生成 JSON 数据的代码可以在任何编程语言编写的。

为什么使用 JSON?

因为 JSON 格式仅仅是文本,它能够轻松地在服务器浏览器之间传输,并用作任何编程语言的数据格式。

JSON 语法规则

  • 数据是名称/值对,键值对
  • 数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组

JSON 格式在语法上与创建 JavaScript 对象的代码相同

JSON 名称需要双引号。JavaScript 名称不需要。

"employees":[
    {"firstName":"Bill", "lastName":"Gates"}, 
    {"firstName":"Steve", "lastName":"Jobs"}, 
    {"firstName":"Alan", "lastName":"Turing"}
]

JSON数组中有三个JSON对象

JavaScript 对象转换为 JSON stringify

var myObj = { name:"Bill Gates",  age:62, city:"Seattle" };
var myJSON =  JSON.stringify(myObj);

JSON对象转换为 JavaScript

var myJSON = '{ "name":"Bill Gates",  "age":62, "city":"Seattle" }';
var myObj =  JSON.parse(myJSON);

JS Async

回调 (callback) 是作为参数传递给另一个函数的函数,允许函数调用另一个函数

function myDisplayer(some) {
  document.getElementById("demo").innerHTML = some;
}

function myCalculator(num1, num2, myCallback) {
  let sum = num1 + num2;
  myCallback(sum);
}

myCalculator(5, 5, myDisplayer)

将函数作为参数传递时不使用括号,以myDisplayer做回调函数

异步:与其他函数并行运行的函数称为异步,异步函数,其中一个函数必须等待另一个函数(例如等待文件加载)

回调最常与异步函数一起使用

在使用 JavaScript 函数 setTimeout() 时,可以指定超时时执行的回调函数

setTimeout(myFunction, 3000)

在使用 JavaScript 函数 setInterval() 时,可以指定每个间隔执行的回调函数

setInterval(myFunction, 1000)
function myCome(val){
	document.getElementById('demo').innerHTML = val;
}
setTimeout(myCome('You are me'),1000)
setInterval(function(){myCome('哈哈h')},3000)

setTime是等待超时,指定超时时执行的回调函数:

setInterval是等待间隔,可以指定每个间隔执行的回调函数