"use strict";
顾名思义也就是 JavaScript 会在所谓严格模式下执行,其一个主要的优点在于可以强制开发者避免使用未声明的变量。对于老版本的浏览器或者执行引擎则会自动忽略该指令。javascript
在正常模式中,若是一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。html
"use strict"; v = 1; // 报错,v未声明 for(i = 0; i < 2; i++) { // 报错,i未声明 }
所以,严格模式下,变量都必须先用var命令声明,而后再使用。java
Javascript语言的一个特色,就是容许"动态绑定",即某些属性和方法到底属于哪个对象,不是在编译时肯定的,而是在运行时(runtime)肯定的。
严格模式对动态绑定作了一些限制。某些状况下,只容许静态绑定。也就是说,属性和方法到底归属哪一个对象,在编译阶段就肯定。这样作有利于编译效率的提升,也使得代码更容易阅读,更少出现意外。程序员
由于下面的代码不是在严格模式下执行,而且this的值不会在函数执行时被设置,此时的this的值会默认设置为全局对象。segmentfault
function f2(){ "use strict"; // 这里是严格模式 return this; } f2() === undefined; // true
更全面的信息参考这个连接浏览器
考虑下面程序的运行结果ide
var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar();
结果是10;
再看下面这个函数
var a = 1; function b() { a = 10; return; function a() {} } b(); alert(a);
结果是1this
出乎意料的结果是因为“Hoisting (变量提高)”的缘由,要理解其中的原理须要先了解下JavaScript的做用域scope。.net
javascript做用域(函数做用域)与C语言做用域(块级做用域)不一样
int main() { int x = 1; printf("%d, ", x); // 1 if (1) { int x = 2; printf("%d, ", x); // 2 } printf("%d\n", x); // 1 }
这是由于C家族的语言有块做用域,当程序控制走进一个块,好比if块,只做用于该块的变量能够被声明,而不会影响块外面的做用域。可是在Javascript里面,这样不行
var x = 1; console.log(x); // 1 if (true) { var x = 2; console.log(x); // 2 } console.log(x); // 2
函数声明和变量声明老是会被解释器悄悄地被“提高”到方法体的最顶部。这个意思是,像下面的代码:
function foo() { bar(); var x = 1; }
实际上会被解释成:
function foo() { var x; bar(); x = 1; }
不管定义该变量的块是否能被执行。下面的两个函数其实是一回事:
function foo() { if (false) { var x = 1; } return; var y = 1; } function foo() { var x, y; if (false) { x = 1; } return; y = 1; }
只有函数式的声明才会连同函数体一块儿被提高。foo的声明会被提高,可是它指向的函数体只会在执行的时候才被赋值
function test() { foo(); // TypeError "foo is not a function" bar(); // "this will run!" var foo = function () { // 变量指向函数表达式 alert("this won't run!"); } function bar() { // 函数声明 函数名为bar alert("this will run!"); } } test();
若是程序员不能很好的理解变量提高,他们写的程序就容易出现一些问题。
为了不这些问题,一般咱们在每一个做用域开始前声明这些变量,这也是正常的 JavaScript 解析步骤,易于咱们理解。
JavaScript 严格模式(strict mode)不容许使用未声明的变量。
function Person (name,age) { this.name = name; this.age = age; this.type = "human"; this.play = function(){console.log("video game")}; } //下面生成实例 var Person1 = new Person("Tom",25); var Person2 = new Person("Jack",26); alert(Person1.name); //这时Person1和Person2会自动含有一个constructor属性,指向它们的构造函数。 alert(Person1.constructor); //Javascript还提供了一个instanceof运算符,验证原型对象与实例对象之间的关系 alert(Person1 instanceof Person); //true alert(Person1.type == Person2.type);//ture alert(Person1.play == Person2.play);//false
type属性和play()方法都是如出一辙的内容,每一次生成一个实例,都必须为重复的内容,多占用一些内存.
Javascript规定,每个构造函数都有一个prototype属性,指向另外一个对象。这个对象的全部属性和方法,都会被构造函数的实例继承。
这意味着,咱们能够把那些不变的属性和方法,直接定义在prototype对象上.
function Person (name,age) { this.name = name; this.age = age; } Person.prototype.type = "human"; Person.prototype.play = function(){console.log("video game")}; var Person1 = new Person("Tom",25); var Person2 = new Person("Jack",26); alert(Person1.type); //human alert(Person1.play == Person2.play); //true
这时全部实例的type属性和play()方法,其实都是同一个内存地址,指向prototype对象,使用原型的好处是可让对象实例共享它所包含的属性和方法,所以就提升了运行效率。
在JavaScript中,一共有两种类型的值,原始值和对象值。每一个对象都有一个内部属性 prototype ,咱们一般称之为原型。原型的值能够是一个对象,也能够是null。若是它的值是一个对象,则这个对象也必定有本身的原型。这样就造成了一条线性的链,咱们称之为原型链。
关于原型、原型链-猛戳
ECMAScript 有 5 种原始类型(primitive type),即 Undefined、Null、Boolean、Number 和 String。
原始数据类型
引用类型一般叫作类(class),也就是说,遇到引用值,所处理的就是对象。
Object 对象
Object 对象自身用处不大,不过在了解其余类以前,仍是应该了解它。由于 ECMAScript 中的 Object 对象与 Java 中的 java.lang.Object 类似,ECMAScript 中的全部对象都由这个对象继承而来,Object 对象中的全部属性和方法都会出如今其余对象中,因此理解了 Object 对象,就能够更好地理解其余对象。
Object 对象具备下列属性
constructor
对建立对象的函数的引用(指针)。对于 Object 对象,该指针指向原始的 Object() 函数。
Prototype
对该对象的对象原型的引用。对于全部的对象,它默认返回 Object 对象的一个实例。
全部程序设计语言最重要的特征之一是具备进行类型转换的能力。
ECMAScript 给开发者提供了大量简单的类型转换方法。