js总结(一):javascript的类型:基本类型、对象和数组
javascript 类型分为2种,一个是原始值,另一个是复杂值(对象)。
一、原始值
5个原始值是:数字,字符,布尔,null,undefined。
9个原生的对象构造函数:Number String Boolean Object Function Array Date Regexp Error
从技术上来讲,从构造函数返回的数字,字符,布尔并不是对象,null和undefined都是非常简单的值,他们不需要构造函数也没有使用new操作符。
typeof "1" "string" typeof 1 "number" typeof a "undefined" typeof true "boolean"
typeof能判断:数字,字符,布尔,object,function,undefined。 注意null和数组,tyopeof都输出object。
如何存储和复制原始值
原始值是真实的值复制
原始值是作为不可细化的值进行存储和操作的
var a =1; var b =a; var a =2; console.log (a,b)// 2 1
var a ={aa:1} var b = a; a.aa =2; console.log(a,b);// Object {aa: 2} Object {aa: 2}
ar a =1; var func = function(num){ num =2 console.log(a); } func(a);\\1
原始值采用的是值比较,对象采用的引用比较
var a =1; var b = new Number(1); var c = Number(1);//没有使用new 因此获得的是原始值 console.log(a==b);\\true console.log(a===b);\\false console.log(a===c);\\true
原始值(String\Number\Boolean)在被用作对象时,就像对象。原始值使用toString方式,,一旦调用或者返回该方法时,对象就会转变成原始值。
如何存储和复制复杂值。复杂值是通过引用进行存储和操作的。复制是复制对象的地址。
复杂值采用引用比较。
var a ={aa:1}; var func = function(num){ num.aa =2 console.log(a);\\ Object {aa: 2} } func(a);
var a ={aa:1}; var func = function(num){ num =2 console.log(a); } func(a);\\Object {aa: 1}
var a ={aa:1}; var func = function(num){ num ={bb:2} console.log(num);\\Object {bb: 2} console.log(a);\\Object {aa: 1} } func(a);
var a = [1,2,3]; var b = function(array){ array.push(4); console.log(array);// [1,2,3,4] } b(a); console.log(a)//[1, 2, 3,4]
var a ={aa:1}; var b ={aa:1}; console.log(a==b);\\false console.log(a===b);\\false
赋值是靠等于号(=),这样相当于是局部变量了,不会对原有的值改变。
相当于都是引用传递,用等于号相当于给变量赋予一个新的地址,如果继续改变原来地址的值,使用其他方法,2个都会变化。
更多请参考:http://www.cnblogs.com/52cik/archive/2014/07/01/js-assignment-operators.html
==和===什么区别?
当时同一个类型时,没有区别。如果不是同一个类型,会进行隐式强制类型转换。
‘’==‘0’//false 0==''//true 0=='0'//true
关于boolean类型,我们记住哪些为假,其他都是true就行了。js的其他任何值都是true,包括new Boolean(false)
0,-0,null,undefined,false,NaN(非数字),空字符串
这些值都是假值,但他们是不可以互换的。
var a = new Boolean(false); if(a){console.log(a)}\\Boolean {[[PrimitiveValue]]: false}
只允许js本身告诉你,这个值是undefined,有东西丢了。如果指定一个对象或者变量等不可以使用,应该使用null,var a =null;
总结下类型
原始值(值类型) 1:基本类型是值类型,可以用typeof判断, 2:占用空间固定保存在栈中 3:保存与复制的是值本身
复杂值 (引用类型 )1:使用new 方法创建的对象,使用instanceof判断类型2:占用空间不固定,保存在堆中 3:保存与复制的是指向对象的指针。
js中一共5个原始值,6个typeof能判断的,9个原生的内置的构造函数。
这5、6、9,构成了js语言的基础。
5个原始值是:数字,字符,布尔,null,undefined
二、typeof操作符
typeof能判断:数字,字符,布尔,object,function,undefined。 注意null和数组,tyopeof都输出object。
9个原生的对象构造函数:Number String Boolean Object Function Array Date Regexp Error
type of Number,返回是function, typeof new Number返回是object。
原生的构造函数从根本上说是用于创建预制对象的模板,用new 操作符来实例化构造函数。
js可以用 字面量,来创建大多数原生对象值。而不必使用new String的方式。
针对字符串、数字和boolean,使用字面量时,只有在该值被视为对象的情况下,才会创建实际的复杂对象。
原始值,这些值是很简单的,不能由其他的值组成,也叫简单值。
typeof不能区分出数组和对象,如何判断类型呢?使用Object.prototype.toString.apply()。
if(value&&typeof value ==='object'&&value.constructor === Array)
上面的检测如果在不同帧和窗口创建的数组,会给出false,window对象不一样了.
可靠的方法是if(Object.prototype.toString.apply(value)==="[object Array]")
arguments 数组不是一个数组,他只是一个有着length成员属性的对象。
如下面例子所示 arguments不是普通的array
var a = function (){
var b = Object.prototype.toString.apply(arguments);
console.log(b);
}
a();//输出[object Arguments]
var a = function (){
var c = [];
var b = Object.prototype.toString.apply(c);
console.log(b);
}
a();//输出[object Array]
如何判断类型
var toString = Object.prototype.toString var isArray = Array.isArray || function(val) { return toString.call(val) === '[object Array]' } var isFunction = function(val) { return toString.call(val) === '[object Function]' }
三、instanceof操作符是如何判断是否实例
prototype里面的属性有constructor.
默认的prototype属性是一个object对象,可以设置为任何复杂值,忽略设置为原始值.
虽然他尽是一个对象,但他是特殊性的,圆形链将每个实例都链接至其构造函数的prototype属性。实例与构造函数的 prototype属性之间有一个隐蔽的链接,这就是实例的__proto__。同时实例的constructor属性是通过构造函数prototype的constructor拿到的。
但是要保留constructor,这样可以让new的实例有constructor的属性,也可以使用instanceof来判断。
var Foo = function(){} Foo.prototype={constructor:Foo} var FooInstance = new Foo; FooInstance.__proto__=== Foo.prototype;//true FooInstance.constructor === Foo; //true
实际上instanceof判断不是依据constructor,而是依据原型链判断,如下面例子
1 var Foo = function(){}; 2 Foo.prototype={}; 3 var FooInstance = {}; 4 FooInstance.__proto__=Foo.prototype; 5 console.log(FooInstance instanceof Foo);//true
使用原始值,不使用构造函数
哪些值算是false:false,"",null,0,-0,NaN,undefined,这些算是false其他都是true
但是请注意下面这个例子
var a = Boolean(false); var b = new Boolean(""); if (a ){console.log(a);}//无法输出 if (b ){console.log(b);}//Boolean {[[PrimitiveValue]]: false} new 一个相当于一个对象了,就不是false
三、关于对象和对象字面量
在javascript中,对象为王;javascript中几乎所有东西都是对象或者用起来像对象。对象只是一组有命名值(也称属性)集合的容器。对象只是属性的容器,每个属性都一个名称和一个值。
var myObject =new Object(); myObject['0']= 'f'; myObject['1']='o'; console.log(myObject);\\ Object {0: "f", 1: "o"}
使用字符串对象,来强调所有东西都是对象
var myObject =new String("fo"); console.log(myObject);\\String {0: "f", 1: "o", length: 2, [[PrimitiveValue]]: "fo"}
var myObject =new Number("111"); console.log(myObject);\\ Number {[[PrimitiveValue]]: 111}
javascript内置了9个原生的对象构造函数,用户也自定义自己的对象构造函数。
对象是拥有名/值得集合,并拥有一个连接到原型对象的隐藏连接。
for in循环仅能遍历可枚举的属性,即在遍历对象时可用的属性,例如构造函数属性就不会被显示。
典型地,预定义的属性不是可列举的,而用户定义的属性总是可列举的。
Object.prototype.bb=2; console.log(Object.prototype["bb"]);\\2 var a ={aa:1} for (var i in a){ console.log(a[i])\\1 2 } Object.prototype = {bb:2};//破坏Object会被屏蔽掉 console.log(Object.prototype.bb)//undefined for (var j in Object.prototype){ console.log(Object.prototype[j])//什么都没有输出 } var a ={aa:1}; for (var i in a){ console.log(a[i])//1 } console.log( a.hasOwnProperty("aa")); //true
使用hasOwnProperty验证对象属性是不是来自于原型链,如果都是继承过来的,就没有
var aaa = { a: 123, b: 456 } var BBB = function (){}; BBB.prototype = aaa; BBB.prototype.c = 789; var bbb = new BBB(); console.log(bbb); for (var i in bbb){ if(bbb.hasOwnProperty(i) ){ console.log(i); console.log(bbb[i]); } }
BBB {a: 123, b: 456, c: 789}
里面的hasOwnProperty没有执行,因为都是别人的,不是自己的。
function testIsEnumerable(){ var a = new Array("apple", "banana", "cactus"); console.log(a.propertyIsEnumerable(1)); } testIsEnumerable()\\true
var a= function (){var bb = 12; this.aa ="xxx"}; a.aa="www"; a.prototype.cc="eee"; a.prototype.dd=function(){}; var b = new a; for (var i in b){ console.log(b[i]); }
关于hasOwnPropery和PropertyIsEnumerable
hasOwnProperty().方法用来检测给定的名字是否是对象的只有属性.对于继承属性它将返回false
propertyIsEnumerable()是hasOwnProperty()的增强版,只有检测到是只有属性且这个属性的可枚举为true是它才返回true.
参考:http://www.zhihu.com/question/21262706/answer/17691563
所以如果你只想遍历对象本身的属性,可以:
for (var key in obj) {
if (obj.hasOwnProperty(key) {
...
}
反过来说,没有必要在 for ... in 中去检测 propertyIsEnumerable,因为不可枚举的属性是不会 for...in 出来的。
propertyIsEnumerable这个方法其实用到的场合非常少,基本上已经被Object.getOwnPropertyDescriptor取代。唯一区别是,后者只能得到own property是否enumerable,而前者包含了整个原型链。
9个原生的对象构造函数
当我们new一个对象的时候 js编译器做了一下操作
1、创建一个新的o 将Person的prototype对象复制给o
2、调用构造函数,this指向o 如 var returnObject = constructor.apply(o,arguments)
3、如果returnObject是一个对象 返回returnObject,否则返回object
参考
http://www.cnblogs.com/RitaRichard/archive/2011/10/12/2208902.html
http://yxc-gdut.iteye.com/blog/1840842
字面量
var a ={aa:1,bb:2};
json的表示方法,属性名永远都是字符串类型,可以不用引号。
点表示方法,用于获取、更新、设置对象的属性都很方便,默认都是字符串,不需要引号。
括号表示法,属性名称在括号内,如果具体的属性名称需要用引号,如果不指定引号,则是变量。
var myObject ={"123":"aa","class":"bb"}; console.log(myObject."123")
var myObject ={"123":"aa","class":"bb"}; console.log(myObject."123") Uncaught SyntaxError: Unexpected string var myObject ={"123":"aa","class":"bb"}; console.log(myObject["123"]) // aa
var myObject ={123:"aa",class:"bb"}; console.log(myObject["123"]+","+myObject["class"]) // aa bb
四、关于数组
http://www.zhangxinxu.com/wordpress/2013/04/es5%E6%96%B0%E5%A2%9E%E6%95%B0%E7%BB%84%E6%96%B9%E6%B3%95/