1,javascript的组成
1,核心(ECMAScript):由 ECMA-262 定义并提供核心功能
2,文档对象模拟器(DOM):提供与网页内容交互的方法和接口
3,浏览器对象模拟器(BOM):提供与浏览器交互的方法和接口。
关于ECMAScript
ECMAScript,即 ECMA-262 定义的语言,Web 浏览器只是 ECMAScript 实现可能存在的一种宿主环境(host environment)。宿主环境提供 ECMAScript 的基准实现和与环境自身交互必需的扩展,包含部分
语法
类型
语句
关键字
保留字
操作符
全局对象
关于dom
DOM 通过创建表示文档的树,让开发者可以随心所欲地控制网页的内容和结构。使用 DOM API,
可以轻松地删除、添加、替换、修改节点。
规范由:DOM Core和DOM HTML
关于BOM
BOM 主要针对浏览器窗口和子窗口(frame),不过人们通常会把任何特定于浏览器的 扩展都归在 BOM 的范畴内。比如,下面就是这样一些扩展
弹出新浏览器窗口的能力;
移动、缩放和关闭浏览器窗口的能力;
navigator 对象,提供关于浏览器的详尽信息;
location 对象,提供浏览器加载页面的详尽信息;
screen 对象,提供关于用户屏幕分辨率的详尽信息;
performance 对象,提供浏览器内存占用、导航行为和时间统计的详尽信息;
对 cookie 的支持;
其他自定义对象,如 XMLHttpRequest 和 IE 的 ActiveXObject。
2,基础语法学习
1,关于变量
var 在 ECMAScript 的所有版本中都可以使用,而 const 和 let 只能在 ECMAScript 6 及更晚的版本中使用。
1,关于var的作用域
使用 var 操作符定义的变量会成为包含它的函数的局部变量,也就是在方法体通过var创建的变量,方法外是无法访问和使用的。
function test() {
var message = "hi"; // 局部变量
}
test();
console.log(message); // 报错
2,关于let的声明
let的作用域是基于块作用域,而var的作用域是基于函数的
if (true) {
let age = 26;
console.log(age); // 有定义
}
console.log(age); // 没有定义
let不允许在一个块作用域两次定义
if (true) {
let age = 26;
let age = 26; // SyntaxError
console.log(age);
}
在for循环的遍历中,如果出现异步的方式进行声明,var会导致有问题,正常理解用var应该打印0,1,2,3,4。实际上会打印5,5,5,5,5
原因:是因为在退出循环时,迭代变量保存的是导致循环退出的值。在之后执行超时,逻辑时,所有的 i 都是同一个变量,因而输出的都是同一个最终值。
for (var i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
3,关于const声明
const 的行为与 let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且 尝试修改 const 声明的变量会导致运行时错误。其实可以理解为const何final很像
const age = 26;
age = 36; // TypeError: 给常量赋值,报错
// const 也不允许重复声明
const name = 'Matt';
const name = 'Nicholas'; // SyntaxError
总结 const,let,var
var的作用域是基于函数的,很容易造成问题,在ES6后,尽量使用const和let,优先使用const,如果当前的变量有变化的话要用let。
数据类型
ES6后,一共包含7种数据类型,Undefined、Null、Boolean、Number、 String 和 Symbol。6个基础,还有一种复杂数据类型叫 Object。
"undefined"表示值未定义;
"boolean"表示值为布尔值;
"string"表示值为字符串;
"number"表示值为数值;:判断是否为数值的(isNaN())
"object"表示值为对象(而不是函数)或 null;
"function"表示值为函数;
"symbol"表示值为符号
3,变量,作用域,内存
1,原始值和引用值
1,原始值就是最简单的数据,引用值:多个值构成的对象
2,原始值复制到新的变量上,是两个值。这里面num1默认为5,num2会复制一个新值,虽然也是5,但是是两个值
let num1 = 5;
let num2 = num1;
3,关于引用传递,obj1和obj2是指向同一个对象的,所以obj2是可以获取到name的值
let obj1 = new Object();
let obj2 = obj1;
obj1.name = "Nicholas";
console.log(obj2.name); // "Nicholas"
2,传递参数
基础数据类型传递,其实就是值的复制,可以通过下面发现,count是复制的一个值传递,如果count+10,不会影响命名的count的值
function addCount(count){
count+10;
}
let count = 10;
addCount(count);
console.log(count); //返回值为10
对象间的引用传递也是基于值传递的,可以发现在作用域内(setName方法),设置的obj新创建一个对象设置name为lisi,但是打印出来的还是zhangsan,说明传递的是obj这个对象的值,而不是引用传递。并且setName执行完成后,对象则会被销毁
function setName(obj){
obj.name = "zhangsan";
obj = new Object();
obj.name = "lisi";
}
let obj = new Object();
setName(obj);
console.log(obj) // 返回{name: 'zhangsan'}
typeof判断基础数据类型的值,对象则用instanceof进行判断
3,内存管理
1,首先垃圾回收方法采用标记清理法。
2,其次在管理内存的时候,当使用v8引擎时,每创建一个类,会有对应的 隐藏类。
3,所以基于性能考虑在创建对象是,最好要共享隐藏类。(V8 在将解释后的 JavaScript 代码编译为实际的机器码时会利用“隐藏类”。)
function persion(){
this.name = 'zhangsan';
}
// 此时,p1和p2是用一个隐藏类型
let p1 = persion();
let p2 = persion();
// 当p2增加属性时,会发现p1和p2不是同一个构造函数,导致需要创建一个隐藏类去监控它
p2.age = 19;
// 所以最好的办法就是在构造器的时候,提前创建好对应的函数
function persion(age){
this.name = 'zhangsan';
this.age = age;
}
let p1 = persion();
let p2 = persion(19);
4,最佳实践方式,在不需要用的对象或者属性时,及时设置为null
p1.age = null;
或者:p1 = null;
4,内存泄漏
1,声明全局变量容易导致内存的泄漏,可以得知window本身不被清理,就会永远占用着,解决方法也很简单,增加var,let,const的命令即可。
// 此时的name为全局变量,既可以使用window.name进行获取内容
function setName(){
name = "lisi";
}
console.log(window.name); // lisi;
2,定时器会造成setInterval方法,只有定时执行,就会不进行收回当前内容
3,使用 JavaScript 闭包很容易在不知不觉间造成内存泄漏
let outer = function() { 10 let name = 'Jake';
return function() {
return name;
};
};
4,基本引用类型
先空着
5,集合引用类型
1,Object
2,Array:数组几组创建方式
let colors = new Array();
let colors = new Array(20);
let colors = new Array("red", "blue", "green");
// 可以通过栈的方式进行获取
colors.push("black");
let item = colors.pop(); // 获取的是black
let queue = colors.shift();
console.log(queue); // 获取red
colors.unshift("white");// 在数组头部增加white
colors.reverse(); // 数组反向排序
colors.sort(); // 数组正向排序
3,map的学习,关于选择方面:map的删除和插入性能更佳。如果量较大可以考虑用map.
// 初始化
const m1 = new Map([
["key1", "val1"],
["key2", "val2"],
["key3", "val3"]
]);
// 也可以传入空
const m1 = new Map();
// 通过set的方式进行添加
m1.set("name","zhangsan").set("age,"lisi");
// 使用hash或者get的方法进行查找
m1.get("name");
m1.has("name");
// delete和clear进行删除,delete是删除某一个key,clear是删除所有
m1.delete("name");
m1.clear();
console.log(m1.size()); // 0
// 与obejct不同,map可以插入任意类型的key
let function = function() {};
m1.set(function,"function");
4,set的学习和weakSet