北纬36度
JavaScript要点笔记

变量提升

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

x = 5; // 变量 x 设置为 5

elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x;                     // 在元素中显示 x

var x; // 声明 x
//结果相同

var x; // 声明 x
x = 5; // 变量 x 设置为 5

elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x;                     // 在元素中显示 x
  • 变量提升:函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部

变量初始化不会提升

var x = 5; // 初始化 x

elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x + " " + y;           // 显示 x 和 y

var y = 7; // 初始化 y
等同于
var x = 5; // 初始化 x
var y;     // 声明 y

elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x + " " + y;           // 显示 x 和 y

y = 7;    // 设置 y 为 7

运行显示y未定义;所谓初始化就是声明的同时附初始值。上面y未被声明的原因是,使用在前,初始化在在后,但初始化不会提升变量
改成如下,可以正常运行,是因为初始化在上,尽管未被提升。

var x = 5; // 初始化 x
var y = 7; // 初始化 y

elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x + " " + y;           // 显示 x 和 y

  • 为了避免这些问题,通常我们在每个作用域开始前声明这些变量,这也是正常的 JavaScript 解析步骤,易于我们理解。
  • JavaScript 严格模式(strict mode)不允许使用未声明的变量。

严格模式

JavaScript 严格模式(strict mode)即在严格的条件下运行。
"use strict" 指令在 JavaScript 1.8.5 (ECMAScript5) 中新增。
它不是一条语句,但是是一个字面量表达式,在 JavaScript 旧版本中会被忽略。
"use strict" 的目的是指定代码在严格条件下执行。

严格模式下你不能使用未声明的变量。

支持严格模式的浏览器:
Internet Explorer 10 +、 Firefox 4+ Chrome 13+、 Safari 5.1+、 Opera 12+。
"use strict";

不允许删除变量或对象

"use strict";
var x = 3.14;
delete x;                // 报错

不允许删除函数。

"use strict";
function x(p1, p2) {};
delete x;                // 报错

不允许变量重名:

"use strict";
function x(p1, p1) {};   // 报错

不允许使用八进制:

"use strict";
var x = 010;             // 报错

不允许使用转义字符:

"use strict";
var x = \010;            // 报错

不允许对只读属性赋值:

"use strict";
var obj = {};
Object.defineProperty(obj, "x", {value:0, writable:false});

obj.x = 3.14;            // 报错

不允许对一个使用getter方法读取的属性进行赋值

"use strict";
var obj = {get x() {return 0} };

obj.x = 3.14;            // 报错

不允许删除一个不允许删除的属性:

"use strict";
delete Object.prototype; // 报错


变量名不能使用 "eval" 字符串:

"use strict";
var eval = 3.14;         // 报错

变量名不能使用 "arguments" 字符串:

"use strict";
var arguments = 3.14;    // 报错

不允许使用以下这种语句

"use strict";
with (Math){x = cos(2)}; // 报错

由于一些安全原因,在作用域 eval() 创建的变量不能被调用:

"use strict";
eval ("var x = 2");
alert (x);               // 报错

禁止this关键字指向全局对象。

function f(){
    return !this;
} 
// 返回false,因为"this"指向全局对象,"!this"就是false

function f(){ 
    "use strict";
    return !this;
} 
// 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。

因此,使用构造函数时,如果忘了加new,this不再指向全局对象,而是报错。

function f(){
    "use strict";
    this.a = 1;
};
f();// 报错,this未定义

保留关键字

为了向将来Javascript的新版本过渡,严格模式新增了一些保留关键字:

implements
interface
let
package
private
protected
public
static
yield

函数

函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。

函数的基本语法

function functionname()
{
    // 执行代码
}

大小写敏感

返回值函数

function myFunction()
{
    var x=5;
    return x;
}

  • 函数内的变量是局部变量函数外声明的是全局变量
  • 声明周期:局部变量函数运行完,全局变量页面关闭
    变量如果没声明就赋值,则会把变量赋值为windows
var var1 = 1; // 不可配置全局属性
var2 = 2; // 没有使用 var 声明,可配置全局属性

console.log(this.var1); // 1
console.log(window.var1); // 1
console.log(window.var2); // 2

delete var1; // false 无法删除
console.log(var1); //1

delete var2; 
console.log(delete var2); // true
console.log(var2); // 已经删除 报错变量未定义

意思是未声明全局变量可以配置也就是可以删除,声明的不可以配置也就是不可以删除

函数表达式即匿名函数

所谓函数表达式就是将函数赋值给一个变量的格式,这个变量以后就可以当做函数来使用,而不是以往只能用带括号的形式调用
另外这种格式,还有另外一种叫法匿名函数

var x = function (a, b) {return a * b};
var z = x(4, 3);

内置构造函数来定义函数

使用函数构造器,通过js内置的函数构造器进行定义

var myFunction = new Function("a", "b", "return a * b");

var x = myFunction(4, 3);
//等同于
var myFunction = function (a, b) {return a * b};

var x = myFunction(4, 3);

函数提升

参见提升
函数可以在声明之前就可以调用。提升将函数的作用域提升到前面

myFunction(5);

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

使用表达式定义函数无法提升

自调用函数

  • 只有函数表达式才能自调用,其格式是在后面加一个括号
(function () {
    var x = "Hello!!";      // 我将调用自己
})();

上面的函数用一个括号括起来的意思是说明这是一个函数表达式-匿名函数

函数可以当做值和表达式使用

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

var x = myFunction(4, 3);

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

var x = myFunction(4, 3) * 2;

函数是对象

在js中任何一个都可以当做对象

在 JavaScript 中使用 typeof 操作符判断函数类型将返回 "function" 。
但是JavaScript 函数描述为一个对象更加准确。
JavaScript的函数是由属性和方法的
比如arguments.length返回函数调用参数个数。

function myFunction(a, b) {
    return arguments.length;
}

toString方法可以函数作为一个字符串返回,运行后整个函数会作为一个字符串输出

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

var txt = myFunction.toString();

函数与对象里的方法的关系

  • 函数如果在所定义对象里出现,叫做对象方法
  • 函数如果用于创建新的对象,叫做对象的构造函数

箭头函数

在es6笔记中提到
声明函数的语法变了,变得更加简洁

(参数1, 参数2, …, 参数N) => { 函数声明 }

(参数1, 参数2, …, 参数N) => 表达式(单一)
// 相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; }

当括号里的参数只有一个的时候,可以把括号省略不写

(单一参数) => {函数声明}
单一参数 => {函数声明}

如果没有参数,则圆括号必须写

() => {函数声明}

es5当前与es6的对比

// ES5
var x = function(x, y) {
     return x * y;
}
 
// ES6
const x = (x, y) => x * y;
  • 有的箭头函数没有自己的this,所以不适合用于对象中的方法,参见对象方法
  • 箭头函数会帮我绑定外层this的值,也就是说一个函数里如果有一个箭头函数,那么在里面的this和外层函数的this所指向的都是外层。参见es6的this
  • 箭头函数不能提升,必须先声明后使用
  • 使用箭头函数最好使用const声明,而不是var,因为函数是个常量
const x = (x, y) => { return x * y };

函数的显式参数和隐式参数

functionName(parameter1, parameter2, parameter3) {
    // 要执行的代码……
}

  • 什么是显式参数:显式参数就是定义函数的时候会显式的指明参数
  • 什么是隐式参数:就是调用函数传递函数真正的值
  • 类似Java中的形参和实参
    参数规则
  • 显式参数不需要指定类数据类型
  • 隐式参数没有类型检测
  • 隐式参数的个数没有限制,不会检测,传几个是几个
  • 在ES5中参数掉用的时候如果没有出入参数,参数默认设置位undefined,但是建议最好设置一个默认值
function myFunction(x, y) {
    if (y === undefined) {
          y = 0;
    } 
}
function myFunction(x, y) {
    y = y || 0;
}

上面面||意思是或的意思,如果函数定义了那么代表是true,如果参数未定义则是undefined代表false,那么会返回0,并赋值给y

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

函数是一个对象,里面内置一个对象,arguments里有函数调用的参数数组

x = findMax(1, 123, 500, 115, 44, 88);
 
function findMax() {
    var i, max = arguments[0];
    
    if(arguments.length < 2) return max;
 
    for (i = 0; i < arguments.length; i++) {
        if (arguments[i] > max) {
            max = arguments[i];
        }
    }
    return max;
}

上面的函数 尽管没有显示参数,但是仍然可以传递参数进去,见显式参数和隐式参数,但是传入的参数如何使用,这时候就可以用arguments对象,这个对象以数组的方式存储函数的参数列表

函数通过值传递参数

函数通过隐式参数将值传入函数内,在函数内修改参数的值,不会影响外部值,也不会影响显示参数的初始值

函数通过对象传递参数

因为是对象,对象是一种引用,所以在函数内修改对象的属性,就会修改其初始值,因为对象是一种引用

函数作为一个函数调用与this的指向

  • 在函数中this的作用:谁调用指向谁
  • 直接调用:函数名(参数列表)

函数不属于任何对象。但是在 JavaScript 中它始终是默认的全局对象。
在 HTML 中默认的全局对象是 HTML 页面本身,所以函数是属于 HTML 页面。
在浏览器中的页面对象是浏览器窗口(window 对象)。以上函数会自动变为 window 对象的函数。
myFunction() 和 window.myFunction() 是一样的:

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

函数中的this
函数中的this指向其谁调用就指向谁因此如果不是被自身调用就会指向被调用者,在web浏览器中就会指向windows对象(浏览器)

function myFunction() {
    return this;
}
myFunction();                // 返回 window 对象

函数作为方法调用与this的指向

函数在对象中叫做方法

var myObject = {
    firstName:"John",
    lastName: "Doe",
    fullName: function () {
        return this.firstName + " " + this.lastName;
    }
}
myObject.fullName();         // 返回 "John Doe"

上述函数做一个对象中的方法,函数同时也是一个对象,其所有者是对象myObject,那么this所代表的是函数的拥有者myObject对象


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

使用构造函数调用函数与this指向

  • 什么是调用函数的构造函数:在调用函数前,前面增加一个new
  • 实际是指调用函数的构造函数,会创建一个新的对象,这个新对象继承了构造函数的属性和方法
// 构造函数:只是函数体内写法不同,其他语法未变
function myFunction(arg1, arg2) {
    this.firstName = arg1;
    this.lastName  = arg2;
}
 
// This    creates a new object
var x = new myFunction("John","Doe");
x.firstName;                             // 返回 "John"

这里的this没有任何的值,只有当函数被调用实例化的时候才会创建,实例化后这里的this是指向新创建对象本身,因为这里是指新创建的实例其继承构造函数中的属性和方法,严格来说已经不叫函数对象

函数的方法调用函数

函数是一种对象,那么对象就有属性和方法
在函数对象中有预定义的两个方法可以调用函数,叫做call()和apply()

<p id="demo"></p>

<script>
var myObject;
function myFunction(a, b) {
    return a * b;
}
myObject = myFunction.call(myObject, 10, 2);    // 返回 20
document.getElementById("demo").innerHTML = myObject; 


<p id="demo"></p>

<script>
var myObject, myArray;
function myFunction(a, b) {
    return a * b;
}
myArray = [10, 2]
myObject = myFunction.apply(myObject, myArray);      // 返回 20
document.getElementById("demo").innerHTML = myObject; 
</script>

在 JavaScript 严格模式(strict mode)下, 在调用函数时第一个参数会成为 this 的值, 即使该参数不是一个对象。
在 JavaScript 非严格模式(non-strict mode)下, 如果第一个参数的值是 null 或 undefined, 它将使用全局对象替代。
通过 call() 或 apply() 方法你可以设置 this 的值, 且作为已存在对象的新方法调用。

两个方法的第一参数都是传入一个对象
不同的是apply第二个参数传入的是数组,而call单独传入

js对象

JavaScript 对象是拥有属性和方法的数据。

在js中什么都是变量

var car = "Fiat";

上面是变量赋值为...
对象是变量,变量也是对象,不同的是对象可以包含多个变量

var car = {type:"Fiat", model:500, color:"white"};

对象定义

var person = {
    firstName:"John",
    lastName:"Doe",
    age:50,
    eyeColor:"blue"
};

对象属性

对象是键值对的容器
所以上面的键值对叫做对象属性

类似
PHP 中的关联数组
Python 中的字典
C 语言中的哈希表
Java 中的哈希映射
Ruby 和 Perl 中的哈希表

访问对象属性

person.lastName;
person["lastName"];

一种类似java对象.属性名,一种类似键值对取值

对象方法

访问

name = person.fullName();

创建

methodName : function() {
    // 代码 
}
var person = {
    firstName: "John",
    lastName : "Doe",
    id : 5566,
    fullName : function() 
	{
       return this.firstName + " " + this.lastName;
    }
};

格式是方法名:function{方法体}
对象的方法和单独创建函数格式不同

作用域

抽象来说js作用域就是变量、对象、函数的集合

局部作用域

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

函数内是局部作用域,声明的变量是局部变量不能再外部使用,函数运行完销毁

全局作用域

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

  • 函数外是全局作用域,声明的变量叫全局变量,任何地方可用,浏览器关闭销毁
  • 没有声明,就赋值,是全局变量,尽管可能在函数体内声明了,如下
  • 函数的参数是局部变量
// 此处可调用 carName 变量
 
function myFunction() {
    carName = "Volvo";
    // 此处可调用 carName 变量
}

变量生命周期

  • 局部变量函数用完就销毁
  • 全局变量浏览器关闭才销毁

HTML全局变量与window对象

window对象是全局变量,同时所有的全局变量都是属于window对象,所以可以如下调用

//此处可使用 window.carName
 
function myFunction() {
    carName = "Volvo";//此处是全局变量因为没有var定义就直接赋值了
}

事件

什么是事件?发生在html元素上的事,比如单击一个按钮
只有你使用了js才会触发这些事件
HTML的事件可以使浏览器的行为,如HTML 页面完成加载,也可是用户行为如1
事件触发可以去执行一些js代码

事件的使用
在HTML元素的属性中有事件属性

<button onclick="getElementById('demo').innerHTML=Date()">现在的时间是?</button>

这里的onclick就是HTML元素的一个属性,事件属性,在属性值里可以书写js代码!
如何调用js代码,比较常见的是在事件的属性值里书写js代码

事件可以用于处理表单验证,用户输入,用户行为及浏览器动作:
页面加载时触发事件
页面关闭时触发事件
用户点击按钮执行动作
验证用户输入内容的合法性
等等 ...
可以使用多种方法来执行 JavaScript 事件代码:

  • HTML 事件属性可以直接执行 JavaScript 代码
  • HTML 事件属性可以调用 JavaScript 函数
  • 你可以为 HTML 元素指定自己的事件处理程序
    你可以阻止事件的发生。
    等等 ..