数据类型: 基本数据类型: Boolean Null Undefined Number String Symbol (ECMAScript 6 新定义) 对象类型 Object 可变性
基本类型:不可变类型,无法添加属性;即使添加属性,解析器无法再下一步读取它;
var cat = "cat"; cat.color = "black"; cat.color // undefined 对象类型:可变类型,支持添加和删除属性。 比较和传递
基本类型:按值比较,按值传递; 对象类型:按引用比较,按引用传递。 // 基本类型 var cat = "tom"; var dog = "tom"; cat === dog // true //对象类型 var cat = {name:"tom"}; var dog = {name:"tom"}; cat === dog //false
我们说的通过引用进行对象比较是:两个对象的值是否相同取决于它们是否指向相同的底层对象 __David Flanagan 改成这样: var cat = {name:"tom"} var dog = cat; b.name = "Haba"
dog === cat // true 如何检测对象类型?或者怎么检测一个数据是数组类型?检测一个对象的类型,强烈推荐使用 Object.prototype.toString 方法; 因为这是唯一一个可依赖的方式。 我们使用Object.prototype.toString方法:Object.prototype.toString.call([]) // "[object Array]" Object.prototype.toString.call({}) // "[object Object]" Object.prototype.toString.call(2) // "[object Number]" typeof只有在基本类型的检测上面才好使,在引用类型(Function除外)里面他返回的都是object,另 typeof null === "object". 很遗憾JavaScript没有类的概念,但它使用构造函数(constructor)作为对象的模板。//构造函数 var Pet = function (name, language) { this.name = name; this.say = function () { console.log(language); } } // new 关键字生成对象 有关new操作符我们在后面会讲到。 var cat = new Pet('tom', 'meow'); cat.name // tom cat.say() // meow
new创建一个对象都进行了那些操作,function Pet () {} var tom = new Pet(); new进行了如下操作:创建一个空对象,用this 变量引用该对象并继承该函数的原型属性和方法加入到this的引用对象中新创建的对象由this所引用,并且最后隐式的返回this模拟过程:function newObj(Fun,arguments) { var o = {}; if (Fun && typeof Fun === "function") { o.proto = Fun.prototype; Fun.apply(o, arguments); return o; } }
模拟过程:function newObj(Fun,arguments) { var o = {}; if (Fun && typeof Fun === "function") { o.proto = Fun.prototype; Fun.apply(o, arguments); return o; } } 这里需要注意的是,构造函数内部有return语句的情况。如果return 后面跟着一个对象,new命令返回return指定的对象;否则不管return语句直接返回this.var Pet = function (name) { this.name = name; return {notInstance:"blabla"} } var cat = new Pet('tom'); cat.name // undefined cat.notInstance // blabla 阐述原型链?js如何实现继承?上面的讲到的构造函数,实例对象的属性和方法都在构造函数内部实现。这样的 构造函数有一个缺点:var cat1 = new Pet('tom', 'meow'); var cat2 = new pet('jery', 'meow'); cat1.say === cat2.say // false 就如JVM虚拟机一样,JS引擎中也有堆(Memory Heap)和栈(Call Stack)的概念。 栈。用来存储方法调用的地方,以及基础数据类型(如var a = 1)也是存储在栈里面的,会随着方法调用结束而自动销毁掉(入栈-->方法调用后-->出栈)。 堆。JS引擎中给对象分配的内存空间是放在堆中的。如var foo = {name: 'foo'} 那么这个foo所指向的对象是存储在堆中的。 JS在浏览器中可以调用浏览器提供的API,如window对象,DOM相关API等。这些接口并不是由V8引擎提供的,是存在与浏览器当中的。因此简单来说,对于这些相关的外部接口,可以在运行时供JS调用,以及JS的事件循环(Event Loop)和事件队列(Callback Queue),把这些称为RunTime。有些地方也把JS所用到的core lib核心库也看作RunTime的一部分。 同样,在Node.js中,可以把Node的各种库提供的API称为RunTime。所以可以这么理解,Chrome和Node.js都采用相同的V8引擎,但拥有不同的运行环境(RunTime Environments)。 JS被设计为单线程运行的,这是因为JS主要用来实现很多交互相关的操作,如DOM相关操作,如果是多线程会造成复杂的同步问题。因此JS自诞生以来就是单线程的,而且主线程都是用来进行界面相关的渲染操作**(为什么说是主线程,因为HTML5 提供了Web Worker,独立的一个后台JS,用来处理一些耗时数据操作。因为不会修改相关DOM及页面元素,因此不影响页面性能)**,如果有阻塞产生会导致浏览器卡死。
如果一个递归调用没有终止条件,是一个死循环的话,会导致调用栈内存不够而溢出,如:
function foo() { foo(); } foo();