浏览器组成
- shell部分
- 内核部分
- 渲染引擎(语法规则和渲染)
- js引擎
- 其他模块
解释型语言 & 编译型语言
- 编译型语言:c c++
- 优点:快
- 不足:移植性不好(不跨平台)
- 解释型语言:python php js
- 优点:跨平台
- 不足:相对慢
- java:
.java --> javac --> 编译 --> .class --> jvm --> 解释执行
单线程
- js单线程 (同一时间只能干一件事)
- 异步:同时进行
- 同步:不同时进行
浏览器内核
浏览器 | 内核 |
---|---|
Chrome | webkit / blink |
IE | trident |
Safari | webkit |
Firefox | Gecko |
Opera | presto |
数据类型
- 原始值:
Number
String
Boolean
undefined
null
- 引用值:
Array
Object
Function
- 原始值变量类型及他们的值存储在栈中 (相当于拷贝变量,在栈中多个变量各存各的值,改变后,互不影响)
- 引用值是把引用变量的名称存储在栈中,把其实际对象存在堆中 (相当于在栈中多个变量存了同一个堆的地址,改变后,最终访问的还是同一地址)
console.log(undefined + undefined); // NaN number类型 console.log(null === null); // true console.log(null + 123); // 123 console.log(Array()); // [] console.log(Object()); // {} console.log(Function()); // function anonymous(){} 匿名函数 console.log(anonymous) // anonymous is not defined var a = 1; console.log(Function(a)); // function anonymous(){ 1 } function b(){ } console.log(b); // function b(){} (function c(){ }) console.log(c); // c is not defined
立即执行函数
只有表达式才能被执行符号执行
(function () {} ());
(function () {} )();
!function () {} (); // !将其转换成了表达式
~function () {} (); // ~将其转换成了表达式
-function () {} (); // -将其转换成了表达式
+function () {} (); // +将其转换成了表达式
var a = ~function () { } console.log(a); // -1 var a = ~function () { return 1 } console.log(a); // -1 var a = ~function () { return 1 }() console.log(a); // -2
堆栈
原始值变量类型及他们的值存储在栈中 (相当于拷贝变量,在栈中多个变量各存各的值,改变后,互不影响)
引用值是把引用变量的名称存储在栈中,把其实际对象存在堆中 (相当于在栈中多个变量存了同一个堆的地址,改变后,最终访问的还是同一地址)
var arr = [1,2]; var arr1 = arr; arr.push(3); // push 操作的是原地址(相当于不改变地址路径,改变地址内(地址指向的堆中)的内容) console.log(arr,arr1); // [ 1, 2, 3 ] [ 1, 2, 3 ] var arr = [1,2]; var arr1 = arr; arr = [1,2,3]; // 等于号操作的是新地址(相当于改变栈中地址的指向,指向一个新地址) console.log(arr,arr1); // [ 1, 2, 3 ] [ 1, 2 ] var a = 1, b = 3; b %= a + 2; // b = b % (a + 2) b = 3 % (1 + 2) b = 0 console.log(a++); // 1 console.log(a); // 2 console.log(--b); // -1
&& 和 ||
&&
: 返回第一个为假的表达式,否则返回最后一个表达式||
: 返回第一个为真的表达式,否则返回最后一个表达式console.log(1 && false && 0); // false console.log(0 || 2 || false); // 2 console.log(1 && false && 0 || 2 || false); // 2 function funA(e){ // event = 非IE浏览器 || IE浏览器 var event = e || window.event; }
练习题
- 2的n次幂
function numA(n) { var num = 2; for (var i = 1; i < n; i++) { num *= 2 } return n === 0 ? 1 : num } console.log(numA(10)); // 1024
- n的阶乘
function numB(n){ return n >= 1 ? n * numB(n-1) : 1; } console.log(numB(3));
- 1 1 2 3 5 8 规律数字
function numC(n){ return n == 1 || n == 2 ? 1 : numC(n-2) + numC(n-1) } console.log(numC(7)); // 13
- 输入123 输出321
function numD(num) { return Number(String(num).split('').reverse().join('')) } console.log(numD(123), typeof nnumD(123)); // 13 number
- 打印n以内的质数 (能从1到他本身只有两个数被他整除的数(相当于只剩下1和他本身了))
function numE(n) { var arr = []; for (var i = 2; i < n; i++) { for (var j = 2; j < i; j++) { if (i % j === 0) { // 跳出循环,在判断是不是他本身,如果不是,证明不是质数,如果是本身,证明已经除到循环结束了,证明他是质数 break; } } if (i === j) { // 判断是不是他本身,如果不是,证明不是质数 arr.push(i) } } return arr; } console.log(numE(100));
typeof
console.log(typeof(typeof(a))); // string
console.log(typeof 1); // number
console.log(typeof NaN); // number
console.log(typeof Infinity); // number
console.log(typeof 'Lee'); // string
console.log(typeof true); // boolean
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(null == null); // true
console.log(null == undefined); // true
console.log(typeof []); // object
console.log(typeof {
}); // object
console.log(typeof function (){
}); // function
console.log([] instanceof Array); // true
console.log([].__proto__ === Array.prototype); // true
console.log([].constructor === Array); // true
console.log(Array.isArray([])); // true
console.log(Object.prototype.toString.call([])); // [object Array]
console.log({
} instanceof Object); // true
console.log({
}.__proto__ === Object.prototype); // true
console.log({
}.constructor === Object); // true
console.log(Object.prototype.toString.call({
})); // [object Object]
显示类型转换(Number
,parseInt
,parseFloat
,toString
,String
,Boolean
)
// Number
console.log(Number('abc')); // NaN
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN
// parseInt
console.log("parseInt('abc')", parseInt('abc')); // NaN
console.log("parseInt(456.789)", parseInt(456.789)); // 456
console.log("parseInt('456.789abc')", parseInt('456.789abc')); // 456
console.log("parseInt(true)", parseInt(true)); // NaN
console.log("parseInt(num,进制)", parseInt(101000, 2)); // 40 从前往后将2进制的101000转换成十进制的数
console.log("parseInt(num,进制)", parseInt(123456789, 2)); // 1 从前往后将2进制的1转换成十进制的数
console.log("parseInt(num,进制)", parseInt(213456789, 2)); // NaN
// parseFloat
console.log("parseFloat('123.456.789abc')", parseFloat('123.456.789abc')); // 123.456
// toString 将数字转换成目标进制
console.log("undefined.toString()", undefined.toString()); // Cannot read property 'toString' of undefined
console.log("null.toString()", null.toString()); // Cannot read property 'toString' of null
// 将二进制101000转换成16进制
console.log("parseInt(101000, 2).toString(16)", parseInt(101000, 2).toString(16)) // 28
隐式类型转换 (isNaN
,运算符
,或且非
)
// isNaN(a) ==> isNaN(Number(a))
console.log("isNaN('abc')", isNaN('abc')); // true
// ++ -- ==>> a++ Number(a)++
console.log("undefined == null", undefined == null); // true
不发生类型转换 (===
!==
)
console.log(undefined === null); // false
函数
- 函数实参和
// 函数实参和 function sum(){ console.log("sum -> arguments", arguments instanceof Object); // true console.log("sum -> arguments", arguments) var res = 0; for (const key in arguments) { if (arguments.hasOwnProperty(key)) { res += arguments[key]; } } return res; } console.log("sum(1,2,3,4)", sum(1,2,3,4)); // 10
- 形式参数:
function aaa(a,b,c){}
实际参数:aaa(1,2,3)
function funA(a){ // arguments和a映射规则,你变我也变 a = 3; console.log("funA -> arguments[0]", arguments[0]) // 3 arguments[0] = 4; console.log("funA -> a", a) // 4 } funA(1); function funB(a,b){ // 实参未传值,实参arguments变化,形参不随之变化 arguments[1] = 3; console.log("funB -> b", b) // undefined // 实参未传值,形参变化,实参arguments不随之变化 b = 4; console.log("funB -> arguments[1]", arguments[1]) // 3 } funB(1);
- js精度不准
0.14 * 100 // 可正常计算的范围为小数点前16位和后16位