1闭包
function close(){
var arr = [1,2,3,4]
for( var i = 0; i < arr.length; i ++){
setTimeout(function(){
console.log(i)
})
}
}
close(arr)//4,4,4,4
复制代码
setTimeout在js单线程中只是放在队列中并未调用,等到主线程任务完成才会执行
链接:JavaScrip同步、异步、回调执行顺序之经典闭包setTimeout分析
function close(){
var arr = [1,2,3,4];
for( var i = 0; i < arr.length; i ++){
(function(i){
setTimeout(function(){
console.log(i)
})
})(i)
}
}
close()//0,1,2,3
复制代码
立即执行函数在每一次循环中执行setTimeout函数并将值传到setTimeout函数中
function close(){
var arr = [1,2,3,4]
for( let i = 0; i < arr.length; i ++){
setTimeout(function(){
console.log(i)
})
}
}
close()//0,1,2,3
复制代码
es6区块作用域变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
2排序
快排
var arr = [1,3,6,2,8,7]
function quickSort(arr){
if (arr.length<=0) {return arr} ;
let mid = arr.splice((arr.length/2),1),
left = [],
right = [];
arr.forEach(function(item){
item < mid ? left.push(item) : right.push(item)
})
return quick(left).concat(mid,quick(right))
}
console.log(qucikSort(arr))//1,2,3,6,7,8
复制代码
"快速排序"的思想很简单,整个排序过程只需要三步:
(1)在数据集之中,选择一个元素作为"基准"(pivot)。
(2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。
(3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。
冒泡排序
var arr = [1,3,6,2,8,7]
function bullSort(arr){
var temp= [];
for(var i = 0; i < arr.length-1; i++){
for(var j = i+1; j < arr.length; j++){
if(arr[i] > arr[j]){
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
return arr
}
console.log(bullSort(arr))//1,2,3,6,7,8
复制代码
随便从数组中拿一位数和后一位比较,如果是想从小到大排序,那么就把小的那一位放到前面,大的放在后面,简单来说就是交换它们的位置,如此反复的交换位置就可以得到排序的效果。
3js继承
类继承
var Father = function(){
this.name = "xiaowang";
this.age = 18;
}
Father.prototype.run = function(){
console.log(this.name+this.age)
}
var Child = function(){
}
Child.prototype = new Father()
var child1 = new Child();
child1.run();//xiaowang18
复制代码
构造函数Child通过prototype(原型)等于构造函数Father的一个实列来继承构造函数Father的所有属性和方法 Child.prototype = new Father() = Father._proto
构造函数继承
//构造函数继承
var Father = function(){
this.name = "xiaowang";
this.age = 18;
};
Father.prototype.run = function(){
console.log(this.name+this.age)
};
var Child = function(){
Father.call(this)
};
var child1 = new Child();
// console.log(child1);
复制代码
构造函数Child通过改变call函数改变this指向来继承构造函数Father的所有属性和方法
Child = this = Father
组合式继承
var Father = function(){
this.name = "xiaowang";
this.age = 18;
};
Father.prototype.run = function(){
console.log(this.name+this.age)
};
var Child = function(){
Father.call(this)
};
Child.prototype = new Father()
var child1 = new Child();
// console.log(child1);
复制代码
class Father{
constructor(color){
this.color = 'red';
};
}
class Child extends Animal{
constructor(){
super();//Father.apply(this)
}
}
var Child1 = new Child()
console.log(Child1)
复制代码
4 this,call,apply,bind
call,apply,bind干什么的?为什么要学这个?在没有学之前,通常会有这些问题。
var a = {
user:"xiaowang",
fn:function(){
console.log(this.user);
}
}
var b = a.fn;
b(); //undefined
复制代码
b方法执行的this是全局window而window是没有定义user这个属性的所以最后结果是undefined。
apply 和 call 的区别:
apply 和 call 基本类似,他们的区别只是传入的参数不同。apply只能传入一个参数但可以是一个数组,而call可以传入多个参数
var a = {
user:"xiaowang",
fn:function(){
console.log(this.user);
}
}
var b = a.fn;
b.call(a); //xiaowang
复制代码
var a = {
user:"xiaowang",
fn:function(){
console.log(this.user);
}
}
var b = a.fn;
b.apply(a); //xiaowang
复制代码
bind方法可以理解为定义了一个方法想要有效果的话必须执行该方法,即后面再加一个括号
var a = {
user:"xiaowang",
fn:function(){
console.log(this.user);
}
}
var b = a.fn;
b.bind(a)(); //xiaowang
复制代码
function log(){
console.log.apply(console, arguments);
};
log("aa","bb")
复制代码
5数组一些方法
1去重
根据json特性不能有相同key值实现
function unique(arr){
var json = {};
for(var i = 0; i < arr.length; i ++){
if(json[arr[i]]){
json[arr[i]]++;
}else{
json[arr[i]]=1;
}
}
console.log(json)
}
复制代码
es6特性数组不可以有相同数字
function unique(arr){
console.log(...new Set(arr))
}
复制代码
第一个和第二个数字对比如果相同则跳过
function unique(arr){
var result = [],
i,
j,
len = arr.length;
for(i = 0; i < len; i++){
for(j = i + 1; j < len; j++){
if(arr[i] === arr[j]){
j = ++i;
}
}
result.push(arr[i]);
}
}
复制代码
2扁平化数组
根据toString将数组变为用,分割的数组字符串然后再转为数字
var flatt= function(){
var arr = [1,2,3,[1,2,3,[1,2,3]]];
var arrstr = arr.toString().split(",")
var arr1 = [];
for(var i = 0; i < arrstr.length; i ++){
arr1.push(Number(arrstr[i]))
}
console.log(arr1)
}
复制代码
使用数组判断方法Array.isArray判断是否为数组,递归操作数组
var arr = [1,2,3,[1,2,3,[1,2,3]]];
var flatt= function(arr){
var res = [];
for(var i = 0; i < arr.length; i ++){
if(Array.isArray(arr[i])){
res = res.concat(flatt(arr[i]))
}else{
res.push(arr[i])
}
}
console.log(res)
}
复制代码
3删除数组中指定的数字
找到要删除数字的索引,使用数组splice方法删除
var delArr = function(){
var arr = [1,2,3,[1,2]];
var res = [1,2]
function getI(arr,res){
for(var i = 0; i < arr.length; i ++){
if(res.toString() == arr[i].toString()){
return i
}
}
}
arr.splice(getI(arr,res),1);
return arr;
}
复制代码
4一个数组中出现次数最多的数字
循环数组使用json统计数字出现的次数,然后枚举json对比一个最大值
var maxNum = function(arr){
var json = {};
for(var i = 0; i < arr.length; i ++){
if(json[arr[i]]){
json[arr[i]]++;
}else{
json[arr[i]]=1;
}
};
// return json
var maxKey = null;
var maxVal = null;
for(name in json){
if(maxVal < json[name]){
maxVal = json[name];
maxKey = name;
}
}
return "出现次数最多的数"+maxKey+"出现了"+maxVal+"次"
};
复制代码
5字符串反转
function reverse(){
var str = "abc";
console.log([...str])
let strarr = [...str].reverse().join("");
console.log(strarr)
}
复制代码
6 浅拷贝深拷贝
浅拷贝只拷贝第一层对象值
function shallowCopy(obj){
let newObj = {}
for(let key in obj){
newObj[key] = obj[key]
}
return newObj
}
复制代码
深拷贝判断对象值是否是对象,是则递归拷贝
function deepCopy(obj){
let newObj = {}
for(let key in obj){
newObj[key] = typeof obj[key] === "object" ? deepCopy(obj[key]) : obj[key]
}
return newObj
}
复制代码
深拷贝新建对象改变值不会影响到原来对象
let obj={
name:"xiaoming",
age:{
name:"xiaolv"
}
}
var a = shallowCopy(obj);
a.age.name= "xiao1"
console.log(a)
console.log(obj)
复制代码
7判断数据类型方式
1 typeof
typeof 是解释器内部实现,根据 ECMA-262规定的几种类型的值来返回类型名称,基本上只能判断出来使用字面量方式赋值的基本数据类型
2 instanceof
instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性,instanceof的局限性应该也就是不能检测基本数据类型了吧,
var arr = [];
arr instanceof Array; // true
复制代码
3 Object.prototype.toString
所有的数据类型都可以用 Object.prototype.toString 来检测,而且非常的精准。 返回'[object object]'字符串
function type(obj) {
var toString = Object.prototype.toString;
var map = {
'[object Boolean]' : 'boolean',
'[object Number]' : 'number',
'[object String]' : 'string',
'[object Function]' : 'function',
'[object Array]' : 'array',
'[object Date]' : 'date',
'[object RegExp]' : 'regExp',
'[object Undefined]': 'undefined',
'[object Null]' : 'null',
'[object Object]' : 'object'
};
return map[toString.call(obj)];
}
复制代码
4 construtor
constructor 属性返回对创建此对象的数组函数的引用,就是返回对象相对应的构造函数。
var arr = [];
arr.constructor == Array; //true
复制代码
链接:数据类型检测
8 原生事件
return 一个实例在原型上添加方法并return this
var navtive = function(){
var G=function(el){
return new G_(el);
}
var G_=function(el){
this.el = document.querySelector(el);
}
G_.prototype.on=function(ev,callback){
this.el.addEventListener(ev,callback,false)
return this
}
G(".native").on("mouseover",function(){
alert(1)
}).on("mouseout",function(){
alert(2)
})
}
// navtive();
复制代码
9 手写一个原生Bind方法
//context为需要被绑定上的对象,arguments是参数
Function.prototype.bind = function(context){
var self = this; //this => Function
return function(){
return self.apply(context,arguments)
}
}
复制代码
//复杂一点的
Function.prototype.bind = function(){
var self = this; //this => Function
var context = [].shift.call(arguments); //arguments 的第一个为需要绑定的this上下文
console.log(context)
var args = [].slice.call(arguments)// arguments除了第一个,成为一个数组
console.log(args)
return function(){
return self.apply(context,[].concat.call(args,[].slice.call(arguments)))
}
}
复制代码
ES6版
Function.prototype.bind = function(that, ...argv) {
if (typeof this !== 'function') {
throw new TypeError(`${this} is not callable`);
}
// 保存原函数
let self = this;
// 获取bind后函数传入的参数
return function(...argu) {
return self.apply(that, [...argv, ...argu]);
};
};
let func1 = function(a, b, c) {
console.log(this.ll);
console.log([a, b, c]);
}.bind(obj, 1, 2);
func1(3); // seve
// [ 1, 2, 3 ]
复制代码
Function.prototype.bind = function() {
if (typeof this !== 'function') {
throw new TypeError(`${this} is not callable`);
}
var self = this;
var slice = [].slice;
// 模拟es6的解构效果
var that = arguments[0];
var argv = slice.call(arguments, 1);
return function() {
// slice.call(arguments, 0)将类数组转换为数组
return self.apply(that, argv.concat(slice.call(arguments, 0)));
};
};
let func2 = function(a, b, c) {
console.log(this.ll);
console.log([a, b, c]);
}.bind(obj, 1, 2);
func2(3); // seve
// [ 1, 2, 3 ]
复制代码
//运行
var obj = {name: 'shaojingjing'}
var func = function(a,b,c,d){
alert(this.name); // shaojingjing
alert([a,b,c,d]) // [1,2,3,44]
}.bind(obj,1,2)(3,4)
复制代码
10原生Ajax
function ajax(){
var ajax = new XMLHttpRequest();
//步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url,可以带参数,动态的传递参数starName到服务端
ajax.open('get','getStar.php?starName='+name);
//步骤三:发送请求
ajax.send();
//步骤四:注册事件 onreadystatechange 状态改变就会调用
ajax.onreadystatechange = function () {
if (ajax.readyState==4 &&ajax.status==200) {
//步骤五 如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的
console.log(xml.responseText);//输入相应的内容
}
}
}
复制代码
11获取一个className
function getObjsByClass(tagName, className){
if(document.getElementsByClassName){
alert("document.getElementsByClassName");
return document.getElementsByClassName(className);
}else{
var el = [];
var _el = document.getElementsByTagName(tagName);
for(var i=0; i<_el.length; i++){
if(_el[i].className.indexOf(className) > -1){
alert(_el[i]);
el[_el.length] = _el[i];
}
}
alert(el);
return el;
}
}
复制代码
12数组转换
1 取值[[1,2]['xiaowang',xiaohong]]
var arr = [{'id':1,'name':'xiaowang'},{'id':2,'name':'xiaohong'},{'id':3,'name':'xiaolv'}]
function getArr(arr){
var newjson = {}
for(var i = 0; i < arr.length; i ++){
for(var key in arr[i]){
if(!newjson[key]){
newjson[key]=[]
}
newjson[key].push(arr[i][key])
}
}
return newjson
}
复制代码
2 1234567890->1,234,567,890
//1黑科技
(123456789).toLocaleString('en-US') // 1,234,567,890
//2js
var test = '1234567890'
function formatCash(str) {
var arr = []
for(var i = 1; i < str.length; i++) {
if(str.length % 3 && i == 1) {
arr.push(str.substr(0, str.length % 3))
}
if(i % 3 === 0) {
arr.push(str.substr(i - 2, 3))
}
}
return arr.join(',')
}
console.log(formatCash(test)) // 1,234,567,890
复制代码
13js获取url参数
function getParams(){
var params = {}
var search = location.search;
search.slice(1).split('&').forEach(function(val){
var arr = val.split('=');
console.log(arr)
params[arr[0]]=arr[1]
})
return params
}
console.log(getParams());**
复制代码