常见习题(持续更新。。。慢慢整理)
最基本的闭包:
-
闭包(closure):函数嵌套函数,什么时候使用? 既能重复使用,又不会污染全局 1、外层函数嵌套内层函数 2、内层函数使用外层函数的局部变量 3、把内层函数作为外层函数的返回值 // 最基本的闭包 function add() { var n = 1 return function(){ return n += 1 } } console.log(add) console.log(add()) let s = add() console.log(s()) console.log(s()) ƒ add() { var n = 1 return function(){ return n += 1 } } ƒ (){ return n += 1 } // 2 // 3
判断一个字符串中出现最多次数的字母?
-
var str = 'asdfssaaasasasasaass' var obj = {} for(var i = 0; i < str.length; i++){ // 判断对象是否有这个字母 // charAt() 方法从一个字符串中返回指定的字符。 if(!obj[str.charAt(i)]){ obj[str.charAt(i)] = 1 }else{ obj[str.charAt(i)]++ } } console.log(obj) var count = 0 var word = '' for(var j in obj){ // 判断最大值,赋值给count if(obj[j] > count){ count = obj[j] word = j } } console.log('出现最多的是字母:'+word+',共计'+count+'次')
判断元素是否为数组的几种方法?
-
Object.prototype.toString.call(arr) // "[object Array]" Array.isArray(arr) // true arr instanceof Array // true // 只适用于对象,即function和array arr.constructor // ƒ Array() { [native code] }
数组去重的几种方法:
-
// 前面2种都是indexOf(),IE8以下不支持 // 方法一 function addNum(arr) { let newArr = []; for (let i = 0; i < arr.length; i++) { if (newArr.indexOf(arr[i]) === -1) // 没有就复制 newArr.push(arr[i]) } return newArr; } console.log(addNum([1, 5,5, 4, 2, 6, 4, 8, '7',7])) // 方法二 function addNum1(arr) { let newArr = []; for (let i = 0; i < arr.length; i++) { if (arr.indexOf(arr[i]) === i) // 没有就复制 newArr.push(arr[i]) } return newArr; } console.log(addNum1([1, 5, 5, 4, 2, 6, 4, 8, '7', 7])) // ES6Set(),Set中的元素只会出现一次,即 Set 中的元素是唯一的。 // Array.from() 方法从一个类似数组或可迭代对象中创建一个新的数组实例。 function addNum2(arr) { return Array.from(new Set(arr)) } console.log(addNum2([1, 5, 5, 4, 2, 6, 4, 8, '7', 7])) // 利用对象属性名不能重复的方式去重,无法区分字符串 function addNum3(arr) { var obj = {} for(let i = 0; i < arr.length; i++){ if(obj[arr[i]]){ arr.splice(i--,1) }else{ // 代表未在obj里 obj[arr[i]] = 999; } } return arr } console.log(addNum3([1, 5, 5, 4, 2, 6, 4, 8, '7', 7])) // 二重循环 function addNum4(arr) { for (let i = 0; i < arr.length-1; i++) { for(let j = i+1; j < arr.length; j++){ if(arr[i] === arr[j]) arr.splice(j--, 1); } } return arr } console.log(addNum4([1, 5, 5, 4, 2, 6, 4, 8, '7', 7,"7"]))
什么是回调函数?
- 回调函数是一段可执行的代码段,它作为一个参数传递给其他的代码,其作用是在需要的时候方便调用这段(回调函数)代码。
JS防抖和节流
先说为什么要做防抖和节流,针对一些会频繁触发的事件,像scroll、resize,如果正常绑定事件处理函数的话,可能在很短的时间内多次连续触发事件,十分影响性能。
所以,针对这种事件要做防抖或者节流处理。
1.防抖
做法就是限制下次函数调用之前必须等待的事件间隔。
实现方法就是维护一个定时器,规定事件后触发函数,规定时间内触发的话,就会取消之前的计时器并且重新设置计时器,这样一来,只有最后一次操作能触发。
2.节流
节流只允许一个函数在规定的时间内触发一次。
它和防抖最大的区别就是,节流函数不管事件触发多频繁,都保证事件处理函数只在规定的时间内触发一次;防抖只是最后一次事件才会触发事件处理函数。
比如在页面无限加载的场景下,我们需要用户在滚动页面时,每隔一段事件发送一次异步请求,而不是用户在停止页面滚动时发送异步请求。所以这种场景,就适合用节流来实现。
两种实现方式:
- 时间戳:容易理解,当高频事件触发时,第一次应该立即执行事件处理函数,然后再怎么频繁触发事件,也都是会等到规定的时间间隔后才执行一次。
- 定时器:当触发事件的时候,设置一个定时器,再触发事件的时候,若定时器是存在, 就什么都不做;知道规定时间后,定时器执行事件处理函数,然后定时器被清空,这样就可以设置下一个定时器。
get和post的区别:
- GET请求在浏览器回退时是无害的,POST会再次提交请求
- GET请求产生的URL地址可以被收藏,而POST不可以
- GET请求会被浏览器主动缓存,而POST不会,除非手动设置
- GET请求只能进行URL编码,而POST支持多种编码方式
- GET请求参数会被完整的保留在浏览器历史记录里,而POST中的参数不会被保留
- GET请求在URL中传递的参数是有长度限制的(不固定,因浏览器决定),而POST没有限制
- GET请求只接受ASC2字符,而对参数的数据类型POST没有限制
- GET请求比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感数据
- GET请求参数通过URL传递,而POST放在request.body上
call、apply、bind之间的区别
总之三种方法都是改变函数内this的指向
1.fn.call (context, arg1, arg2, …)
call中第一个参数是fn的上下文,剩下的参数就是需要向fn中传递的参数
2.fn.apply (context, [args])
apply同call类似,第一个参数也是fn的上下文,和call不同的是,apply第二个参数是数组,call的第二个及第二个以后的参数都是数组里面的元素
3.fn.bind (context)
bind会创建一个函数,称之为绑定函数,调用这个函数时,绑定函数会以创建它是bind方法传入的第一个参数作为自己的上下文,第二个及第二个以后的参数并且加上绑定函数运行时传递进来的参数作为原函数的参数来调用原函数。 (有点绕哈,不过对下一道题有帮助)
4.call、apply、bind最大的区别就是bind不会立即调用,会返回一个函数,apply、call会立即调用。
-
什么是可扩展标记语言(XML)?
- 可扩展标记语言是一种很像超文本标记语言的标记语言。
- 它的设计宗旨是传输数据,而不是显示数据。
- 它的标签没有被预定义。您需要自行定义标签。
- 它被设计为具有自我描述性。
- 它是W3C的推荐标准。
可扩展标记语言和超文本标记语言之间的差异
- 它不是超文本标记语言的替代。
- 它是对超文本标记语言的补充。
- 它和超文本标记语言为不同的目的而设计:
- 它被设计用来传输和存储数据,其焦点是数据的内容。
- 超文本标记语言被设计用来显示数据,其焦点是数据的外观。
- 超文本标记语言旨在显示信息;而XML旨在传输信息,它是独立于软件和硬件的信息传输工具。
数组常见API
<script>
var arr = [1,2,4];
var arr1 = [5,7,8];
var arr2 = arr.concat(arr1,arr1);// [1,2,4,5,7,8,5,7,8]
// concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
// 注意:数组/值在连接时保持不变。此外,对于新数组的任何操作(仅当元素不是对象引用时)都
// 不会对原始数组产生影响,反之亦然。
// console.log(arr2);// 1,2,4,5,7,8,5,7,8
// // join() 方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。
// // PS: join() 方法,不会改变数组,可以将数组转换成字符串!
// console.log(arr2.join("-"));// 1-2-4-5-7-8-5-7-8
// pop、push修改的是数组本身,删除的是最后一个
// pop()方法从数组中删除最后一个元素,并返回该元素的值(被删除的元素)。此方法更改数组的长度。
// push() 方法将一个或多个元素添加到数组的末尾,并返回值是该数组的新长度。
// var num = arr.pop();
// console.log(arr);// 1,2,4,5,7,8,5,7
// console.log(num);// 8
// var len = arr.push(6,10);
// console.log(arr);// 1,2,4,6,10
// console.log(len);// 5
// shift、unshift修改的是数组本身
// shift() 方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
// unshift() 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度。
// var num = arr.shift();
// console.log(arr);// 2,4
// console.log(num);// 1
// var len = arr.unshift(1,2);
// console.log(arr);// 1,2,2,4 会去点第一个元素在添加你要添加的元素
// console.log(len);// 4
// reverse() 方法将数组中元素的位置颠倒。
// 第一个数组元素成为最后一个数组元素,最后一个数组元素成为第一个,结果改变原数组。
// var arr3 = arr.reverse();
// console.log(arr3);// 4,2,1
// slice() 方法返回一个新的数组对象,这一对象是一个由 begin和 end(不包括end)
// 不传参数代表对原数组的浅拷贝(复制)。原始数组不会被改变。
// var arr4 = arr2.slice(1); //从当前下标截取到末尾
// console.log(arr4);// [2,4,5,7,8,5,7,8]
// var arr5 = arr2.slice(1,3); //截取下标1-3的元素(含头不含尾)
// console.log(arr5);// [2,4]
// var arr6 = arr2.slice(5,-2); //负数指的是从右往左数第几个
// console.log(arr6);// [8,5]
// splice()方法通过删除现有元素和替换或添加新元素来修改数组,并以数组返回原数组中被修改的内容。
// var arr7 = arr2.splice(1,5);// 删除下标1-5的元素
// console.log(arr2);// 1,5,,7,8
// console.log(arr7);// 表示被删除的元素 // 2,4,5,7,8
// arr2.splice(2,2,100,200);// 表示从下标为2的元素开始,替换4,5为100,200
// console.log(arr2);// 1,5,100,200
// arr2.splice(3,0,250);// 表示从下标为3的元素开始,添加一个值为250的元素
// console.log(arr2);// 1,5,100,250,200
// sort() 方法用原地算法对数组的元素进行排序,并返回数组。排序算法现在是稳定的。
// 默认排序顺序是根据字符串Unicode码点。
var arr10 = [2,4,3,5,9,7,6,3,89];
var arrsort = arr10.sort(function(a,b){
//指定规则,规则大于0,ab交换位置
// return a-b;// 由小到大
return b-a;// 由大到小
});
console.log(arrsort);
// 字符串排序,利用的是ASCLL码
console.log("a">"b"); // false,a的ASCLL码小于b
console.log("ab"<"b");// true,对应位置先比较,a<b
</script>
ES5新增数组常见方法
2个索引方法:indexOf() 和 lastIndexOf();
5个迭代方法:forEach()、map()、filter()、some()、every();
2个归并方法:reduce()、reduceRight();
var arr = [1,7,5,2,4,6,1,4];
// 2个索引方法:indexOf() 和 lastIndexOf();
// indexOf()方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
console.log(arr.indexOf(1)); // 0
console.log(arr.indexOf("1")); // -1
// lastIndexOf() 方法返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个
// 的索引,如果不存在则返回 -1。从数组的后面向前查找,从 fromIndex 处开始。
console.log(arr.lastIndexOf(1)); // 6
// 5个迭代方法:forEach()、map()、filter()、some()、every();
// forEach() 方法对数组的每个元素执行一次提供的函数。
arr.forEach(function(item,i){
console.log(item,i);// item代表的是数组里面的元素,i是它对应的下标
});
// map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
var arrmap = arr.map(function(item,i){
return item * 2;
});
console.log(arrmap);
// filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
var arrfilter = arr.filter(function(item,i){
return item > 4;
// return i >4; // 下标大于4的
})
console.log(arrfilter);
// some() 方法测试数组中的某些元素是否通过由提供的函数实现的测试。
var arrsome = arr.some(function(item,i){
// return item > 7; // false
return item < 7; // true
})
console.log(arrsome);// 返回的结果是布尔类型
// every() 方法测试数组的所有元素是否都通过了指定函数的测试。
var arrevery = arr.every(function(item,i){
// return item > 7; // false
return item < 7; // false
})
console.log(arrevery);// 返回的结果是布尔类型
// 2个归并方法:reduce()、reduceRight();
// reduce() 方法对累计器和数组中的每个元素(从左到右)应用一个函数,将其简化为单个值。
// 注意:如果没有提供初始值,reduce会从索引1的地方开始执行,跳过第一个索引。如果提供初
// 始值,则从索引0(提供的初始值)开始。
var arr1 = [4,2,6,3,7,5];
// 把上一次迭代return的结果作为下一次的初始值(prev)
var sum = arr.reduce(function(prev,next){
return prev + next;
});// 累加数组里的所有值
console.log(sum);
var sum1 = arr.reduce(function(prev,next){
console.log(next);
return prev * next;
},1);// 1为初始值
console.log(sum1);
// reduceRight() 方法接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)
var sum2 = arr.reduceRight(function(prev,next){
console.log(next);
return prev * next;
},1);
console.log(sum2);
String常用API
<script>
// 创建字符串的2种方式:
var str = "hello";
var str2 = "world";
var str1 = new String("Hello");
console.log(str);
console.log(str1);
console.log(str[4]); // o
// charAt() 方法返回在指定位置的字符
console.log(str.charAt(4)); // o
// indexOf() 方法检索字符串,返回下标
console.log(str.indexOf("o")); // 4
// lastIndexOf() 方法从后向前搜索字符串。
console.log(str.lastIndexOf("e")); // 1
// charCodeAt() 方法返回在指定的位置的字符的 Unicode 编码。
console.log(str.charCodeAt(2)); // l的Unicode编码是108
// 静态 String.fromCharCode() 方法返回使用指定的Unicode值序列创建的字符串。
console.log(String.fromCharCode(66,67,68)); // BCD
// concat() 方法将一个或多个字符串与原字符串连接合并,形成一个新的字符串并返回。
console.log(str.concat(str2)); // helloworld
// match() 方法找到一个或多个(正则表达式的)匹配。。
console.log(str.match("l")); // ["", index: 0, input: "hello"]
// replace() 方法替换与正则表达式匹配的子串。
console.log(str.replace("e","a"));
// search() 方法检索与正则表达式相匹配的值。
console.log(str.search("e"));
// slice() 方法提取一个字符串的一部分,并返回一新的字符串。语法:str.slice(beginSlice[, endSlice])
console.log(str.slice(1)); // ello
console.log(str.slice(1,3)); // el 含头不含尾
// split() 方法使用指定的分隔符字符串将一个String对象分割成字符串数组,以将字符串分隔
// 为子字符串,以确定每个拆分的位置。
console.log(str.split("e"));
// substr() 方法返回一个字符串中从指定位置开始到指定字符数的字符,返回的是一个新的字符串。
// 语法:str.substr(start[下标, length])
console.log(str.substr(1,2));
// substring() 方法返回一个字符串在开始索引到结束索引之间的一个子集, 或从开始索引直到字符串的末尾的一个子集。
// 语法:str.substring(indexStart[, indexEnd])
console.log(str.substring(0,3)); // 只含头不含尾
// toUpperCase() 方法把字符串转换为大写。
console.log(str.toUpperCase());
// toLowerCase() 把字符串转换为小写。
console.log(str1.toLowerCase());
// 去掉字符串前后空格(ES5)trimleft/trimRight
var str3 = " e n d ";
console.log(str3.trim());
// startsWith() 方法用来判断字符串是否以某个字符开头(ES6),判断结果返回 true 或 false。
console.log(str.startsWith("a")); // false
// endsWith() 方法用来判断字符串是否以某个字符结尾(ES6),判断结果返回 true 或 false。
console.log(str.endsWith("o")); // true
// includes() 方法字符串是否包含某个字符(ES6),判断结果返回 true 或 false。
console.log(str.includes("o")); // true
// repeat() 方法用来检查重复某个字符串几次(ES6),重复不能负数
console.log(str.repeat(2)); // hellohello
</script>
隐式转换等于false
NaN,undefined,null,0,"" 通过3目运算来间接验证
javaScript内置对象(十个)
- Object对象 是所有JavaScript对象的超类(基类)
- Array对象 数组对象–定义数组属性和方法
- Boolean对象 布尔对象–布尔值相关
- Date对象 日期对象–日期时间相关
- Error对象 错误对象–处理程序错误
- Function对象 函数对象–定义函数属性和方法
- Math对象 数学对象–各种数学运算工具(不是构造函数)
- Number对象 数字对象–定义数字属性和方法
- RegExp对象 正则表达式对象–定义文本匹配与筛选规则
- String对象 字符串对象–定义字符串属性和方法
## 事件
- e.offsetX / offsetY 获取事件触发最近的盒子(事件源)的坐标
- e.clientX / clientY 获取可视区的坐标(根据浏览器的定位)
- e.screenX / screenY 获取整个屏幕的坐标
- 鼠标事件兼容:e = e || window.event
- 键盘事件兼容:e.keyCode || e.which
- 默认行为:e.preventDefault() window.returnValue = false
- 阻止冒泡:e.stopPropagation() e.cancelBubble=true // 兼容IE
- 一个完整事件包含 捕获阶段 ---> 目标阶段 --->冒泡阶段
- 事件监听:addEventListener() removeEventListener() attachEvent() detachEvent()
- 判断事件源:e.target || e.srcElement
cookie
注意:cookie是http/https协议下的技术,不支持本地file文件对cookie操作
一个网站从打开到浏览(包括这个网站的其他子页面)到最后关闭浏览器整个过程叫一个“会话”。
- 只能存文本
- 不能大于4KB
- 数量限制
- 读取有域名限制,不可跨域读取
- 时效限制(expires)
正则
- [ ] 中括号:匹配其中的某一个字符
-^ (不在中括号里)匹配字符串开头
- $ 匹配结尾
- /^ $/ 这样的正则代表完整匹配
- \d ---- [0-9] 数字
- \w -----[a-z0-9_] 数字,字母,下划线
- \s --- 空白字符
- \D -----[^0-9] 非数字
- \W -----[^a-z0-9_] 非数字,字母,下划线
- \ S -----非空白字符
- . -----全部字符
- \b -----匹配单词边界
- \B -----匹配 非 单词边界
- \0(数字0) -----匹配 NULL 字符
- \n -----匹配 换行符
- \f -----匹配 换页符
- \r -----匹配 回车符
- \t -----匹配 制表符
- \v -----匹配 垂直制表符
- \u4e00 - \u9fa5 验证中文
- {n} ---匹配n次
- {n,m} ---最少n次,最多m次;
- QQ号验证 /^[1-9]\d{4,10}$/
- {n,} ---最少n次,最多不限
- + {1,}
- ? {0,1} 可有可无,最多一个
- * {0,} 可以有也可以没有,个数不限
- i:忽略大小写
- g:全局查找
- m: 多行查找(必须与g一起实用,并且,当使用^和$模式时才会起作用)
test方法
该方法用来测试某个字符串是否与正则匹配,匹配就返回true,否则返回false
- var reg = /(^\s*)|(\s*$)/g
str.replace(reg,"")
ES5严格模式
- 全局变量声明时 必须加var
- this 无法指向全局对象
- .函数内重名属性
- arguments对象不允许动态改变/不允许自调用
- 新增保留字; implements, interface, let, package, private, protected, public, static, yield。
实用的数组对象的API
JSON.parse(str); //json序列化,将符合json格式的字符串转换为json
JSON.stringify(); //json转换为字符串
Date.now(); //日期对象得到当前日期的毫秒数
Object.keys(obj); //获取obj的所有属性名称,返回数组
Object.values(obj); // 获取obj的所有属性值,返回数组
Object.defineProperty(obj, prop, descriptor); //给obj设置属性
如何使用:
var obj = new Object();
Object.defineProperty(obj, 'name', {
configurable: false, // 表示能否通过delete删除此属性
writable: true, // 能否修改属性的值
enumerable: true, // 表示该属性是否可枚举,即是否通过for-in循环或Object.keys()返回属性
value: '张三'
})
console.log(obj.name)
var obj = new Object();
Object.defineProperties(obj, {
name: {
value: '张三',
configurable: false,
writable: true,
enumerable: true
},
age: {
value: 18,
configurable: true
}
})
console.log(obj.name, obj.age) // 张三, 18
暂时性死区
var a = 10;
if(true){
console.log(a);//ReferenceError(引用错误): a is not defined;
let a = 20;
}
一旦用let或const声明一个变量,那么这个区块就变成块级作用域,用let 或者const声明的变量即为该区块绑定, 该变量不受任何变量影响。 在该变量使用let声明前不可以用。在语法上,我们叫这种情况为:暂时性死区 (temporal dead zone,简称 TDZ)
扩展运算符: ... 把数组解构出来
rest运算符: ... 可以用于把属性合并进数组
for...of...: 可以用来遍历一个字符串
Set集合是默认去重复的
基本数据类型何引用数据类型
undefined、null、boolean、string、number、symbol(Symbol函数会生成一个唯一的值可以理解为Symbol类型跟字符串是接近的)
object、function
ES6语法糖
1.对象字面量:
var phone = {}
2.new运算符创建:
var phone = new Object({})
3.构造函数
用来构造(创建)对象的函数
他在声明的时候跟普通函数没有区别
用new运算符加上函数的调用,调用的结果就是一个对象
构造函数中的this指的是即将要new的那个对象
4.ES6语法糖
// 解构赋值
// 构造函数生成实例:
//函数名和实例化构造名相同且大写(非强制,但这么写有助于区分构造函数和普通函数)
function Person(name,age) {
this.name = name;
this.age=age;
}
Person.prototype.say = function(){
return "我的名字叫" + this.name+"今年"+this.age+"岁了";
}
var obj=new Person("laotie",88);//通过构造函数创建对象,必须使用new 运算符
console.log(obj.say());//我的名字叫laotie今年88岁了
// ES6class类,更像一种面向对象的语言
class Person{//定义了一个名字为Person的类
constructor(name,age){//constructor是一个构造方法,用来接收参数
this.name = name;//this代表的是实例对象
this.age=age;
}
say(){//这是一个类的方法,注意千万不要加上function
return "我的名字叫" + this.name+"今年"+this.age+"岁了";
}
}
var obj=new Person("laotie",88);
console.log(obj.say());//我的名字叫laotie今年88岁了
注意项: 1.在类中声明方法的时候,千万不要给该方法加上function关键字
2.方法之间不要用逗号分隔,否则会报错
class不存在变量提升,所以需要先定义再使用。因为ES6不会把类的声明提升到代码头部,但是ES5就不一样,ES5存在变量提升,可以先使用,然后再定义。
什么是面向对象
-
对象的本质:属性和方法的集合
-
程序:数据结构+算法
-
OOA面向对象分析(Object-Oriented Analysis):将大问题拆分成小问题,并试图用分工协作来完成 的思维方式。
-
OOD面向对象设计(Object-Oriented Design):
-
分析模块后,确定职责。
-
确定耦合关系(如何交流?模块关系:高内聚,低耦合)
-
为OOP做准备
-
-
OOP面向对象编程(Object-Oriented Programming):类和对象的关系?
-
对象的三大特点:封装(写对象,用对象)、继承(子对象可以使用父对象的一些属性和方法)、多态(重载、重写)
JS同步和异步的区别?
- JS是单线程的,所有同步任务都在主线程上执行,形成一个执行栈,主线程之外还存在一个异步队列,用于存储异步操作,一旦执行栈中所有的同步操作执行完毕,再执行异步队列里面的异步操作。
- 同步:会被阻塞,前一个加载完后一个才能加载
- 异步:不会被阻塞,常见的异步操作有ajax请求,动态渲染img,设置定时器
AJAX
- json是一种数据格式,由对象,数组互相嵌套组成,属性名必须加双引号,数据传输格式
由于 Ajax 包含众多特性,优势与不足也非常明显。优势主要以下几点:
1.不需要插件支持(一般浏览器且默认开启 JavaScript 即可);
2.用户体验极佳(不刷新页面即可获取可更新的数据);
3.提升 Web 程序的性能(在传递数据方面做到按需放松,不必整体提交);
4.减轻服务器和带宽的负担(将服务器的一些操作转移到客户端);
而 Ajax 的不足由以下几点:
1.不同版本的浏览器度 XMLHttpRequest 对象支持度不足(比如 IE5 之前);
2.前进、后退的功能被破坏(因为 Ajax 永远在当前页,不会记录前后页面);
3.搜索引擎的支持度不够(因为搜索引擎爬虫还不能理解 JS 引起变化数据的内容);
// 最基本的ajax
// get
var ajax = new XMLHttpRequest();
ajax.open("GET","url",true); //get请求,url请求地址,true代表异步
ajax.send();
ajax.onreadystatechange = function(){
if(ajax.readyState == 4 && ajax.status == 200{
console.log(ajax.responseText);
}
}
// post
var ajax = new XMLHttpRequest();
ajax.open("POST","url",true);
ajax.setRequestHeader("Content-type","application/x-www-form-urlencoded");
ajax.send("name=zhangsan&age=18");
ajax.onreadystatechange = function(){
if(ajax.readyState == 4 && ajax.status == 200){
var json = JSON.parse(ajax.responseText);
fn(json);
}
同源策略:
浏览器安全策略,保障非同源资源之间数据访问的安全性,默认不允许非同源的资源直接访问。
URL:
协议://域名:端口/路径名称?查询字符串#位置标识符
同源:协议、域名、端口完全一致,只要三个中有任何一个不一致,则是非同源
解决资源跨域访问:
a. CORS
cross-origin resource sharing
服务器端:
设置响应头信息: Access-Control-Allow-Origin:*
前端:
ajax
可解决GET/POST跨域需求
b. jsonp
<script src=""></script>
利用<script>在引入外部JS时不受同源策略限制的特性,来实现跨域。
JSONP只能处理GET请求方式的跨域
后端:
由服务器端构建一个字符串:字符串中的内容是能够在 JS 中执行的函数调用的结构
前端:
1. 创建 <script> 元素
2. 设置 src 属性,传递 callback 参数指明全局回调函数的名称
3. 添加到 body 中
4. 创建全局函数,用于处理响应数据
5. 删除 <script> 元素
promise(ES6)
三种状态:pending(进行中),resolve(兑现),rejectd(失信)
语法:new Promise((resolve,rejecct) => {
}).then(() => {
}).catch(error => {
}).finally(() => {
})
Promise.all([promise1,promise2,promise3]).then(() => {
})
继承
1.原型链继承:子类的原型指向父类的实例
2.构造继承(call、apply继承)
3.拷贝继承 子类通过for in浅拷贝父类的方法和变量
4.组合继承(原型链和构造继承的组合)
5.寄生组合继承 了解就行
6.ES6语法糖继承 子类通过extends实现对父类方法变量的继承
设计模式:
1.工厂模式
2.单例模式
3.观察者模式(发布订阅模式)
4.策略模式
5.代理模式
webpack
node是一个运行js的环境(服务器运行)
Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。
npm 包管理工具
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
- 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
使用webpack
webpack之间模块的关系遵循CommonJS规范
导出模块
module.exports = {}
引入模块
const header = require("./header.js");
全局安装:npm install -g webpack@3
根目录新建webpack.config.js文件
module.exports = {
//项目入口文件
entry : "./js/index.js",
//编译之后的输出文件信息
output : {
//编译之后的文件路径
path : __dirname + "/dist",
//编译之后的文件名称
filename : "bundle.js"
}
};
y继承)
3.拷贝继承 子类通过for in浅拷贝父类的方法和变量
4.组合继承(原型链和构造继承的组合)
5.寄生组合继承 了解就行
6.ES6语法糖继承 子类通过extends实现对父类方法变量的继承
设计模式:
1.工厂模式
2.单例模式
3.观察者模式(发布订阅模式)
4.策略模式
5.代理模式
## webpack
node是一个运行js的环境(服务器运行)
Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。
npm 包管理工具
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
- 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
使用webpack
webpack之间模块的关系遵循CommonJS规范
导出模块
module.exports = {}
引入模块
const header = require("./header.js");
全局安装:npm install -g webpack@3
根目录新建webpack.config.js文件
module.exports = {
//项目入口文件
entry : “./js/index.js”,
//编译之后的输出文件信息
output : {
//编译之后的文件路径
path : __dirname + “/dist”,
//编译之后的文件名称
filename : “bundle.js”
}
};
转载:https://blog.csdn.net/marendu/article/details/101671983