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());**
複製程式碼