JavaScript 字面量 和 变量html
var a; //只是声明变量而没有赋值,则该变量的值是undefined var b = 666;
c = 222; // 变量赋值的时候,忘了写命令,这条语句也是有效的。
// 不写的作法,不利于表达意图,并且容易不知不觉地建立全局变量
// 因此建议老是使用命令声明变量。
console.log(ddd); // 变量没有声明就直接使用,会报错,告诉你变量未定义varvarvar
JavaScript 标识符面试
指 js 中能够由咱们命名的名字。。。如变量名,函数名... ...编程
var 临时变量 = 1;
学习 js 三部分数组
JavaScript 有六种数据类型 (ES6 又新增了第七种 Symbol 类型的值)浏览器
\uxxxx
的形式,其中xxxx
表明该字符的 Unicode 码点。好比,\u00A9
表明版权符号。
var s = '\u00A9'; // s = "©" var f\u006F\u006F = 'abc'; // foo = "abc";
btoa():任意值转为 Base64 编码 atob():Base64 编码转为原来的值 var string = 'Hello World!'; btoa(string) // "SGVsbG8gV29ybGQh" atob('SGVsbG8gV29ybGQh') // "Hello World!" btoa('你好') // 不适合非 ASCII 码的字符,会报错 function b64Encode(str) { return btoa(encodeURIComponent(str)); } function b64Decode(str) { return decodeURIComponent(atob(str)); } b64Encode('你好') // "JUU0JUJEJUEwJUU1JUE1JUJE" b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"
isFinite()
方法返回一个布尔值,表示某个值是否为正常的数值。
isFinite(Infinity) // false isFinite(-Infinity) // false isFinite(NaN) // false isFinite(undefined) // false // 其余都返回 true isFinite(null) // true isFinite(-1) // true
// parseInt() 获取字符串中整数部分 // 利用 parseInt("",num) 进行进制转换 parseInt('1000', 10) // 1000 parseInt('1000', 2) // 8 parseInt('1000', 6) // 216 parseInt('1000', 8) // 512 // parseFloat() 获取字符串中的浮点数部分 parseFloat('314e-2') // 3.14 parseFloat('0.0314E+2') // 3.14 若是字符串符合科学计数法,则会进行相应的转换 parseFloat('\t\v\r12.34\n ') // 12.34 自动过滤字符串前导的空格
NaN
是 JavaScript 的特殊值,表示“非数字”(Not a Number),主要出如今将字符串解析成数字出错的场合。isNaN
为true
的值,有可能不是NaN
,而是一个字符串typeof NaN // 'number NaN === NaN // false NaN不等于任何值,包括它自己。 Boolean(NaN) // false [NaN].indexOf(NaN) // -1 5 - 'x' // NaN Math.acos(2) // NaN Math.log(-1) // NaN Math.sqrt(-1) // NaN 0 / 0 // NaN NaN + 32 // NaN NaN - 32 // NaN NaN * 32 // NaN NaN / 32 // NaN
isNaN('Hello') // true // 至关于 isNaN(Number('Hello')) // true
// 判断更可靠的方法是,利用为惟一不等于自身的值的这个特色,进行判断。
NaNNaN
function myIsNaN(value) { return value !== value; }
// Infinity大于一切数值(除了NaN),-Infinity小于一切数值(除了NaN) 1 / -0 // -Infinity 负无穷 -1 / -0 // Infinity 正无穷 Infinity === -Infinity // false // 场景一 Math.pow(2, 1024) // Infinity 计算结果太大,超出了可以表示的范围 // 场景二 0 / 0 // NaN 1 / 0 // Infinity
// 第1位: 符号位,0表示正数,1表示负数 // 第2位到第12位(共11位): 指数部分 // 第13位到第64位(共52位): 小数部分(即有效数字) // 第1位:符号位,0表示正数,1表示负数 // 第2位到第12位(共11位):指数部分 // 第13位到第64位(共52位):小数部分(即有效数字) // (-1)^符号位 * 1.xx...xx * 2^指数部分 // 上面公式(指数部分在0到2047之间),一个数在 JavaScript 内部实际的表示形式。 // 精度最多只能到53个二进制位, // 这意味着,绝对值小于2的53次方的整数,即-253到253,均可以精确表示。 // 9007199254740992111 // 9007199254740992000 // 上面示例代表,大于2的53次方之后,多出来的有效数字(最后三位的111)都会没法保存,变成0。
64 位浮点数的指数部分的长度是 11 个二进制位,意味着指数部分的最大值是2047(2的11次方减1)。服务器
也就是说,64 位浮点数的 指数部分 的值最大为 2047,分出一半表示负数,则 JavaScript 可以表示的数值范围为2的1024到2-1023(开区间),超出这个范围的数没法表示。
若是一个数大于等于2的1024次方,那么就会发生“正向溢出”,即 JavaScript 没法表示这么大的数,这时就会返回Infinity。模块化
Math.pow(2, 1024) // Infinity
若是一个数小于等于2的-1075次方(指数部分最小值-1023,再加上小数部分的52位),那么就会发生为“负向溢出”,即 JavaScript 没法表示这么小的数,这时会直接返回0。函数式编程
Math.pow(2, -1075) // 0
0.1 + 0.2 === 0.3 // false 0.3 / 0.1 // 2.9999999999999996 (0.3 - 0.2) === (0.2 - 0.1) // false
+0
或-0
看成分母,返回的值是不相等的。
(1 / +0) === (1 / -0) // false // 上面的代码之因此出现这样结果, // 是由于除以正零获得+Infinity,除以负零获得-Infinity, // 这二者是不相等的
转换规则是除了下面六个值被转为false, 其余值都视为true。 undefined null false 0 NaN "" 或 '' (空字符串)
变量 a
分别被赋值为undefined
和null
,这两种写法的效果几乎等价。函数
在if
语句中,它们都会被自动转为false
,相等运算符(==
)甚至直接报告二者相等。学习
if (!undefined) { console.log('undefined is false'); } // undefined is false if (!null) { console.log('null is false'); } // null is false undefined == null // true
null
表示"无"。根据 C 语言的传统,null
能够自动转为0
Number(null) // 0 5 + null // 5
null
就像在 Java 里同样,被当成一个对象,Brendan Eich 以为表示“无”的值最好不是对象。
其次,那时的 JavaScript 不包括错误处理机制,Brendan Eich 以为,若是null
自动转为0,很不容易发现错误。
所以,他又设计了一个undefined
。
区别是这样的:
null
是一个表示“空”的对象,转为数值时为0
;
undefined
是一个表示"此处无定义"的原始值,转为数值时为NaN
。
Number(undefined) // NaN 5 + undefined // NaN
// 变量声明了,但没有赋值 var i; // i = undefined // 调用函数时,应该提供的参数没有提供,该参数等于 undefined function f(x) { return x; } f() // x = undefined // 对象没有赋值的属性 var o = new Object(); o.p // o.p =undefined // 函数没有返回值时,默认返回 undefined function f() {} ret = f() // ret = undefined
普通对象Object
数组对象Array
函数对象Function
宿主对象
自定义对象
var x = 'sex';
var obj = { foo: 'Hello', bar: 'World',
[x]: "男" };
// 属性的值仍是一个对象,就造成了链式引用。
Object.keys
方法。
var obj = { key1: 1, key2: 2 }; Object.keys(obj); // ['key1', 'key2']
delete
命令用于删除对象的属性,删除成功后返回 true
var obj = { p: 1 }; Object.keys(obj) // ["p"] delete obj.p // true obj.p // undefined Object.keys(obj) // []
// 注意: 删除一个不存在的属性,不报错,并且返回
deletetrue
只有一种状况,delete
命令会返回false
,那就是该属性存在,且不得删除。
// Object.defineProperty() 建立的对象obj的p属性是不能删除的, var obj = Object.defineProperty({}, 'p', { value: 123, configurable: false }); obj.p // 123 delete obj.p // false 因此delete命令返回false
即便delete
返回true
,该属性依然可能读取到值。
var obj = {}; delete obj.toString // true obj.toString // function toString() { [native code] } // 上面代码中,toString是对象obj继承的属性, // 虽然delete命令返回true,但该属性并无被删除,依然存在
var obj = { p: 1 }; 'p' in obj // true 'toString' in obj // true // toString() 方法是继承的 // 使用对象的hasOwnProperty方法判断,是否为对象自身的属性 var obj = {}; if ('toString' in obj) { console.log(obj.hasOwnProperty('toString')) // false } // for...in循环用来遍历一个对象的所有属性。 // 遍历的是对象全部可遍历(enumerable)的属性,会跳过不可遍历的属性 // 对象都继承了toString属性,可是for...in循环不会遍历到这个属性 // 关于对象属性的可遍历性,参见《标准库》章节中 Object 一章的介绍。 var obj = {a: 1, b: 2, c: 3}; for (var i in obj) { console.log('键名:', i); console.log('键值:', obj[i]); } // 使用for...in的时候,应结合 hasOwnProperty(),在循环内判断,某个属性是否为对象自身的属性。 var person = { name: '老张' }; for (var key in person) { if (person.hasOwnProperty(key)) { console.log(key); } } // name
// 例一 , 设置已有属性 var obj = { p1: 1, p2: 2, }; with (obj) { p1 = 4; p2 = 5; } // 必须是当前对象已经存在的属性,不然创造一个当前做用域的全局变量
// 等同于 obj.p1 = 4; obj.p2 = 5;
// 例二 访问已有属性 with (document.links[0]){ console.log(href); console.log(title); console.log(style); }
// 等同于 console.log(document.links[0].href); console.log(document.links[0].title); console.log(document.links[0].style);
这是由于with
区块没有改变做用域,它的内部依然是当前做用域。这形成了with
语句的一个很大的弊病,就是绑定对象不明确。
x
究竟是全局变量,仍是对象obj
的一个属性。这很是不利于代码的除错和模块化,编译器也没法对这段代码进行优化,只能留到运行时判断,这就拖慢了运行速度。所以,建议不要使用with
语句,能够考虑用一个临时变量代替with
。面试题
1. a[变量] 其中 a 是一个对象,使用 [] 来读写对象,会调用 .toString() 将 变量 隐式转换 为 字符串
var a{}; var b = { n: 2 }; var c = { m: 3 }; a[b] = 4; // a[b.toString()] = 4 a["object Object"] = 4 a[c] = 5; // a[c.toString()] = 5 a["object Object"] = 5 console.log(a[b]); // 打印 5
== 会进行复杂的 隐式类型转换
=== 会进行 数据类型 和 值 的比较
三种方法 肯定一个值是什么数据类型
typeof 123 // "number" typeof '123' // "string" typeof false // "boolean" typeof typeof 123 // "string" 由于 typeof 返回值是 string
// 函数返回function function f(){} typeof f // "function" // 对象返回object typeof window // "object" typeof {} // "object"
/**** 一个数组 也返回 object ****/
typeof [] // "object" /**** null 返回 object 表示将要做为对象使用 ****/ typeof null // "object" // undefined 返回 undefined typeof undefined // "undefined" // typeof能够用来检查一个没有声明的变量,而不报错。 console.log(typeof a); // 返回一个字符串 "undefined" // 实际编程中,这个特色一般用在判断语句 // 错误的写法 if (v) { // ... } // ReferenceError: v is not defined // 正确的写法 if (typeof v === "undefined") { // ... }
// 空数组([])的类型也是object,这表示在 JavaScript 内部,数组本质上只是一种特殊的对象。 // 这里顺便提一下,instanceof运算符能够区分数组和对象。var o = {}; var a = []; o instanceof Array // false 对象不是数组类型的 a instanceof Array // true 数组是对象类型的
变量类型: 变量的类型其实是变量内存中数据的类型
数据对象:
数据
即存储于内存中表明特定信息的东东,本质就是 01 二进制。
具备 可读 、可传递 的基本特性,一切皆数据
数据运行于内存中,读写速度快。
垃圾回收机制: 当堆中的一个对象,再也没有任何一个变量指向它,则将在一段时间后被销毁
因此,咱们再也不须要某个对象时,只须要 obj = null; 便可
变量