Javascript是一门面向对象的,跨平台的脚本语言。css
做用域:变量的做用范围,主要有如下几种:html
做用范围为整个程序的执行范围,在函数体外部定义的变量就是全局变量,在函数体内部不使用var定义的也是全局变量。前端
做用范围是某个函数体内部,在函数体内部经过var关键字定义的变量或者形参,都是局部变量,当局部变量与全局变量重名时,在函数体内部局部变量优先于全局变量。vue
变量的声明会提高至当前做用域的最顶端,但不会提高赋值web
在相同的函数或块做用域内从新声明同一个变量会引起SyntaxError;面试
在声明变量或常量以前使用它, 会引起ReferenceError. 这就是暂存性死区。正则表达式
这里主要存在两个坑点:编程
switch (x) {
case 0: let foo; break; case 1: let foo; // TypeError for redeclaration. break; } 复制代码
会报错是由于switch中只存在一个块级做用域, 改为如下形式能够避免:api
let x = 1;
switch(x) { case 0: { let foo; break; } case 1: { let foo; break; } } 复制代码
function test(){ var foo = 33; if (true) { let foo = (foo + 55); // ReferenceError } } test(); 复制代码
在if语句中使用了let声明了foo, 所以在(foo+55)中引用的是if块级做用域中的foo, 而不是test函数中的foo; 可是因为if中的foo尚未声明完。数组
在这一行中,if块的“foo”已经在词法环境中建立,但还没有达到(并终止)其初始化(这是语句自己的一部分)
所以它仍处于暂存死区
全局变量的生命周期直至浏览器卸载页面才会结束。 局部变量只在函数的执行过程当中存在,而在这个过程当中会为局部变量在栈或堆上分配相应的空间,以存储它们的值,而后再函数中使用这些变量,直至函数结束
执行环境执行栈(也称执行上下文–execution context)。
当JavaScript解释器初始化执行代码时,它首先默认进入全局执行环境,今后刻开始,函数的每次调用都会建立一个新的执行环境,每个执行环境都会建立一个新的环境对象压入栈中。
当执行流进入一个函数时,函数的环境对象就会被压入一个环境栈中(execution stack)。在函数执行完后,栈将其环境弹出,把控制权返回给以前的执行环境。
除了正常运行模式,ECMAscript 5 添加了第二种运行模式:"严格模式"(strict mode)。顾名思义,这种模式使得Javascript在更严格的条件下运行。其主要有下面这几个目的:
"严格模式"体现了Javascript更合理、更安全、更严谨的发展方向,包括IE 10在内的主流浏览器,都已经支持它。
一样的代码,在非严格模式下能够运行,可是严格模式下可能将不能运行。
<script>
"use strict" console.log("已经进入严格模式"); </script> 复制代码
<script>
"use strict" a = 10;//报错 由于 a没有被var 声明 //Uncaught ReferenceError: a is not defined; 引用错误: a 没有被声明 </script> 复制代码
<script>
"use strict" // console.log("已经进入严格模式"); function a(){ this.b = 10; //报错 , 由于this指向了window对象; //Uncaught TypeError: Cannot set property 'b' of undefined; 类型错误 : 不能给undefined设置属性b; } window.a(); </script> 复制代码
<script>
"use strict"; function a(b,b,c){ //报错 console.log(b,b,c); // 正常模式下 2,2,3 // Uncaught SyntaxError: Duplicate parameter name not allowed in this context ;语法错误:在此上下文中不容许重复的参数名称 } a(1,2,3) </script> 复制代码
arguments对象不容许被动态改变;
<script>
function fn1(a) { a = 2; return [a, arguments[0]]; } console.log(fn1(1)); // 正常模式为[2,2] function fn2(a) { "use strict"; a = 2; return [a, arguments[0]]; } console.log(fn2(1)); // 严格模式为[2,1] </script> 复制代码
arguments对象不容许被自调用
<script>
"use strict"; var f = function() { return arguments.callee; }; f(); // 报错 //Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them //类型错误:“caller ”,“arguments.callee ”,不能在严格模式中使用; //caller返回调用当前函数的函数的引用 (正在执行的函数的属性) // callee返回正在执行的函数自己的引用 (arguments的属性) </script> 复制代码
this是js的关键字,他是根据执行上下文(执行环境)动态指向当前调用的对象; 谁调用,就指谁;
call()、apply()、bind() 能够改变this的指向
js语言中一切皆为对象,好比数字、字符串、数组、Math、Object、函数
js中对象的本质:属性和方法的集合(无序,因此对象没有length属性)。
用官方一点的语言来解释对象:
什么是对象,其实就是一种类型,即引用类型。而对象的值就是引用类型的实例。在 ECMAScript 中引用类型是一种数据结构,用于将数据和功能组织在一块儿。它也常被称作为类,但 ECMAScript6之前却没有这种东西。虽然 ECMAScript 是一门面向对象的语言,却不具有传统面向对象语言所支持的类等基本结构。
封装、继承、多态
一、写对象
二、用对象
把一些相关的对象和属性放到一块儿,用一个变量抽象出来,那么这就完成了这个对象的封装
子承父业
子对象可使用父对象的一些属性和方法
重载,重写
重载就是根据不一样的参数类型,参数个数实现不一样的功能
重写就是父类的方法很差用,我本身从新定义一个方法名相同的不一样方法
var obj = { 键值对 key:value } 复制代码
var obj = new Object() 复制代码
function Person(name,age,job){
this.name= name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); } } var person1 = new Person('monkey',30,'web'); var person2 = new Person('zhu',25,'h5'); 复制代码
工厂模式抽象了建立具体对象的过程。因为在ECMAScript中没法建立类,开发人员就发明了一种函数,用函数来封装以特定接口建立对象的细节,以下面的例子:
function createPerson(name,age,job){
var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); } return o; } var person1 = createPerson('monkey',30,'web'); var person2 = createPerson('zhu',25,'h5'); 复制代码
class Point {
constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } } 复制代码
字符串的两种建立方式(常量和构造函数),经常使用api有:
Math的经常使用属性有:
经常使用api有:
经常使用api有:
上学时,班上的同窗会进行分组,以下图,一竖排是一组
一列就是一个数组,一个数组里面有不少个元素(多个同窗),由于js是弱类型语言,因此数组也是弱类型,同一个数组变量里能够有各类不一样类型的元素。
var arr = [];
复制代码
var arr = new Array(); //构造函数的方式 var arr = new Array(10);//一个参数指数组长度为10 var arr = new Array(10,20,30);//多个参数指定义数组元素 复制代码
ES5新增数组方法
判断一个元素是否存在于数组中,若不存在返回-1,若存在就返回它第一次出现的位置
lastIndexOf() 方法可返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索
循环遍历数组中的每个元素,这个函数包含三个形参,分别为:item, index, array, 用不到时能够不写
返回一个新数组,新数组是原数组的映射,不改变原数组,新数组的元素值是每次函数return的返回值,若不写return,接收的新数组的元素值将全为空
过滤元素,返回一个新数组,新的数组由每次函数返回值为true对应的元素组成; 原数组不受影响
return返回的值只要有一项为true,最终的返回值就为true,不会继续遍历后边的元素,若没有一项知足返回值为true的,就返回false,原数组不受影响;
对数组的每一项执行给定的函数,假如该函数每一项都返回true,最后结果才为true;只要有一项返回值为false,最后结果就是false。且后边的元素都不会再继续执行函数;原数组不受影响
reduce() 方法接收一个函数做为累加器,数组中的每一个值(从左到右)开始缩减,最终计算为一个值。reduce() 能够做为一个高阶函数,用于函数的 compose
reduce() 对于空数组是不会执行回调函数的
reduceRight() 方法的功能和 reduce() 功能是同样的,不一样的是 reduceRight() 从数组的末尾向前将数组中的数组项作累加。
reduceRight() 对于空数组是不会执行回调函数的
ES6新增数组方法
传入一个回调函数,找到数组中符合当前搜索规则的第一个元素,返回它,而且终止搜索
传入一个回调函数,找到数组中符合当前搜索规则的第一个元素,返回它的下标,而且终止搜索
用新元素替换掉数组内的元素,能够指定替换下标范围。
格式:arr.fill(value, start, end)
选择数组的某个下标,从该位置开始复制数组元素,默认从0开始复制。也能够指定要复制的元素范围。
格式:arr.copyWithin(被替换的起始位置,选取替换值的起始位置,选取替换值的结束位置)
将相似数组的对象(array-like object)和可遍历(iterable)的对象转为真正的数组
用于将一组值,转换为数组
返回迭代器:返回键值对
返回键值对的value
返回键值对的key
判断数组中是否存在该元素,参数:查找的值、起始位置,能够替换 ES5 时代的 indexOf 判断方式。indexOf 判断元素是否为 NaN,会判断错误。
块级做用域:一种广泛存在于各个语言中的做用域范围;
三个点号,功能是把数组或类数组对象展开成一系列用逗号隔开的值
var foo = function(a, b, c) {
console.log(a); console.log(b); console.log(c); } var arr = [1, 2, 3]; //传统写法 foo(arr[0], arr[1], arr[2]); //使用扩展运算符 foo(...arr); //1 //2 //3 复制代码
rest运算符也是三个点号,不过其功能与扩展运算符刚好相反,把逗号隔开的值序列组合成一个数组
//主要用于不定参数,因此ES6开始能够再也不使用arguments对象
var bar = function(a, ...args) { console.log(a); console.log(args); } bar(1, 2, 3, 4); //1 //[ 2, 3, 4 ] 复制代码
ES6中存在一种新的字符串, 这种字符串是 以 (波浪线上的那个字符 > 反引号)括起来表示的; 一般咱们想要拼接一个带有标签的字符串, 是用这样的方式:
bianliang + " <strong>这是一个文字" + obj.name + "</strong> " + bianliang
复制代码
可是有了ES6字符串一切都变得很是简单了;
` ${bianliang} <strong>这是一个文字${obj.name}</strong>${bianliang} `
复制代码
用 ${ } 扩住变量让拼接变得很是容易;
原来的写法
var test = function(x){
return x+2; } 复制代码
使用箭头函数:
var test = x =>x+2;
var 函数名 = 参数 => 运算规则; 复制代码
箭头函数this指向的固定化,并非由于箭头函数内部有绑定this的机制,实际缘由是箭头函数根本没有本身的this,致使内部的this就是外层代码块的this。正是由于这个,因此箭头函数也不能作构造函数。主要有两个缺陷:
var [a,b,c] = [1,2,3];
var {a,b,c} = { a:1, b:2, c:3 } var username = "zhangsan"; var age = 18; var obj = {username,age}; 复制代码
想当初设计JS的时候,因为有SUN公司人员的参与 再加上当时如日中天的JAVA及其优秀的设计,才使得JS语法及内存设计跟JAVA会如此的接近。但JAVA不少优秀的内容,JS不知道为了什么目的并无引入,例如Set和Map集合
Set集合,本质上就是对数组的一种包装 例如:
let imgs = new Set();
imgs.add(1); imgs.add(1); imgs.add(5); imgs.add("5"); imgs.add(new String("abc")); imgs.add(new String("abc")); // 打印的结果: 1 5 '5' 'abc' 'abc' 复制代码
Set集合是默认去重复的,但前提是两个添加的元素严格相等 因此5和"5"不相等,两个new出来的字符串不相等
关于遍历的方法 因为Set集合本质上仍是一个map,所以会有如下几种奇怪的遍历方法
var imgs = new Set(['a','b','c']);
//根据KEY遍历 for(let item of imgs.keys()){ console.log(item); } //a //b //c 复制代码
//根据VALUE遍历
for(let item of imgs.values()){ console.log(item); } //a //b //c 复制代码
//根据KEY-VALUE遍历
for(let item of imgs.entries()){ console.log(item); } //['a','a'] //['b','b'] //['c','c'] 复制代码
//普通for...of循环(for...of跟for-in的区别很明显,就是直接取值,而再也不取下标了)
for(let item of imgs){ console.log(item); } //a //b //c 复制代码
SET集合没有提供下标方式的访问,所以只能使用for来遍历。
// 下面展现了一种极为精巧的数组去重的方法
var newarr = [...new Set(array)];
Map集合,即映射
let map = new Map();
map.set("S230", "张三"); map.set("S231", "李四"); map.set("S232", "王五"); 获取某一个元素 map.get("s232"); //王五 复制代码
//循环遍历,配合解构赋值
for(let [key,value] of map){
console.log(key,value); } 复制代码
BOM(Browser Object Model 浏览器对象模型),结构以下图所示:
window是全局浏览器内置顶级对象,表示浏览器中打开的窗口(没有应用于window对象的公开标准,不过全部浏览器都支持该对象)。
在客户端 JavaScript 中,Window 对象是全局对象,全部的表达式都在当前的环境中计算。
也就是说,要引用当前窗口根本不须要特殊的语法,能够把那个窗口的属性做为全局变量来使用。
例如,能够只写 document,而没必要写 window.document。
一样,能够把当前窗口对象的方法看成函数来使用,如只写 alert(),而没必要写 Window.alert()。
除了上面列出的属性和方法,Window 对象还实现了核心 JavaScript 所定义的全部全局属性和方法。
全局变量默认是挂在window下的,例如:
var a = 123; alert(window.a)//123 复制代码
location:
通常状况下给reload()传递一个true,让他刷新,并不使用缓存。缓存的东西通常为js文件,css文件等。用这个方法可让本身不能动的页面动起来了。刷新当前页面。
window.navigator:
以上属性已经在逐渐被抛弃了。
一个新的属性将替代这些属性。
navigator.userAgent 返回浏览器信息(可用此属性判断当前浏览器)
判断当前浏览器类型的,示例:
function isBrowser() {
var userAgent = navigator.userAgent; //微信内置浏览器 if(userAgent.match(/MicroMessenger/i) == 'MicroMessenger') { return "MicroMessenger"; } //QQ内置浏览器 else if(userAgent.match(/QQ/i) == 'QQ') { return "QQ"; } //Chrome else if(userAgent.match(/Chrome/i) == 'Chrome') { return "Chrome"; } //Opera else if(userAgent.match(/Opera/i) == 'Opera') { return "Opera"; } //Firefox else if(userAgent.match(/Firefox/i) == 'Firefox') { return "Firefox"; } //Safari else if(userAgent.match(/Safari/i) == 'Safari') { return "Safari"; } //IE else if(!!window.ActiveXObject || "ActiveXObject" in window) { return "IE"; } else { return "未定义:"+userAgent; } } 复制代码
history:
screen: 屏幕
window下的弹框方法:
DOM(Document Object Model 文档对象模型),DOM定义了表示和修改文档所需的对象、行为和属性,以及这些对象之间的关系。
获得的是一个集合(不止一个,是一堆)
不是全部的标签都有name值,低版本的浏览器会有兼容问题
IE8如下不能用
历史好文推荐:
一、【万字长文】史上最强css、html总结~看完涨薪再也不是梦
我是monkeysoft,你的【三连】就是monkeysoft创做的最大动力,若是本篇文章有任何错误和建议,欢迎你们留言!
文章持续更新,能够微信搜索 【小猴子的web成长之路】关注公众号第一时间阅读,关注以后后台回复知识体系,更可领取小编精心准备的前端知识体系,将来学习再也不迷茫,更可加入技术群交流讨论。
本文使用 mdnice 排版