js基礎(chǔ)2

  • localStorage 永久存儲(chǔ)

本地永久存儲(chǔ)晌纫,就算你關(guān)閉了瀏覽器,數(shù)據(jù)依然存在,除非你手動(dòng)清空掉它

  1. localStorage.setItem(鍵名,鍵值) 設(shè)置存儲(chǔ)
  2. localStorage.getItem(鍵名) 獲取存儲(chǔ)值
  3. localStorage.removeItem(鍵名) 移除存儲(chǔ)值
  4. localStorage.clear() 清空所有會(huì)話存儲(chǔ)
<button onclick="saveData()">存儲(chǔ)</button>
<button onclick="getData()">獲取</button>
<button onclick="removeData()">移除name</button>
<button onclick="clearData()">清空</button>

<script>
function saveData(){
  localStorage.setItem('name','張三');
  localStorage.setItem('age','24');
  localStorage.setItem('sex','24');
  alert('存儲(chǔ)成功爆价!');
}
function getData(){
  alert( localStorage.getItem('name') );
}
function removeData(){
  alert( localStorage.removeItem('name') );
}
function clearData(){
  localStorage.clear();
  alert('清空了禁熏!');
}
</script>

在早期瀏覽器不支持html5本地存儲(chǔ)壤巷,那么使用cooike存儲(chǔ),cookie存儲(chǔ)大小有限制瞧毙,大小4KB胧华,存儲(chǔ)數(shù)量也有限制,一個(gè)網(wǎng)站大概50多個(gè)宙彪,cookie它一個(gè)時(shí)效性矩动,我們可以給cookie設(shè)置一個(gè)保存時(shí)間,怎么刪除cookie呢释漆?設(shè)置cookie的時(shí)間為過去時(shí)間悲没。

  • 創(chuàng)建cookie

不加過期時(shí)間的話,屬于會(huì)話存儲(chǔ)男图,關(guān)閉瀏覽器數(shù)據(jù)消失

cookie是明文存儲(chǔ)示姿,不可以直接把重要信息(密碼)存入cookie

//關(guān)閉瀏覽器,會(huì)被自動(dòng)回收
document.cookie="username=龔賢";

//加上過期時(shí)間
document.cookie="username=龔賢;expires=Thu, 18 Dec 2043 12:00:00 GMT;";

//加上使用路徑權(quán)限逊笆,/代表當(dāng)前根目錄
document.cookie="username=龔賢;expires=Thu, 18 Dec 2043 12:00:00 GMT;path=/";
  • 獲取cookie

設(shè)置cookie和獲取cookie是同一個(gè)方法

console.log( document.cookie );//username=龔賢
  • 刪除cookie

刪除cookie栈戳,只需要設(shè)置一個(gè)過期的時(shí)間,刪除cookie一般是需要關(guān)閉整個(gè)瀏覽器之后生效览露。

注意:chrome需要以服務(wù)器的方式訪問荧琼,cookie才能生效,本地靜態(tài)方式訪問無(wú)效(file://)

注意:有時(shí)候設(shè)置了關(guān)閉瀏覽器后cookie才能清除

示例

  
  <button onclick="setItem()">存儲(chǔ)cookie</button>
  <button onclick="getItem()">讀取cookie</button>
  <button onclick="delItem()">刪除cookie</button>

  <script>
  function setItem(){
    document.cookie="username=老三&age=33&sex=男;expires=Thu, 18 Dec 2043 12:00:00 GMT;path=/";
    alert('存儲(chǔ)成功差牛!');
  }
  function getItem(){
    var str = document.cookie; // username=老三&age=33&sex=男
    var params = new URLSearchParams( str );
    console.log( params.get('username') );//老三
    console.log( params.get('age') ); //33
    console.log( params.get('sex') ); // 男
  }
  function delItem(){
    //注意chrome瀏覽器
    document.cookie="; expires=Thu, 01 Jan 1970 00:00:00 GMT";
    alert('刪除成功命锄!');
  }
  </script>

cookiesessionStroagelocalStroage 之間的區(qū)別

存儲(chǔ)大衅:

  • cookie數(shù)據(jù)大小不能超過4k脐恩。
  • 本地存儲(chǔ)有存儲(chǔ)大小的限制,可以達(dá)到5M或更大侦讨。

生命周期:

  • cookie 設(shè)置過期時(shí)間之前一直有效驶冒,即使窗口或?yàn)g覽器關(guān)閉
  • localStorage 存儲(chǔ)持久數(shù)據(jù),瀏覽器關(guān)閉后數(shù)據(jù)不丟失除非主動(dòng)刪除數(shù)據(jù)
  • sessionStorage 數(shù)據(jù)在當(dāng)前瀏覽器窗口關(guān)閉后自動(dòng)刪除

some() 只要一個(gè)成員的返回值是true韵卤,那么結(jié)果就是true骗污。

該方法返回布爾類型(true/false)

var data = [
  { id:1,name:'張三'},
  { id:2,name:'李四'}
]

var result = data.some(function( item ){
  return item.name == '張三';
})

console.log( result );//true

every() 每一個(gè)成員都返回值是true,那么結(jié)果就是true沈条。

該方法返回布爾類型(true/false)

//示例一
var data = [
  { id:1,name:'張三',score: 70},
  { id:2,name:'李四',score: 56}
]
var result1 = data.every(function( item ){
  return item.score >= 60 ;
})

console.log( result1 ); //false需忿,因?yàn)槔钏奈醇案瘢苑祷丶?
//示例二
var data = [
  { id:1,name:'張三',score: 70},
  { id:2,name:'李四',score: 66}
]
var result2 = data.every(function( item ){
  return item.score >= 60 ;
})
console.log( result2 );// true,每個(gè)成員都及格了屋厘,所以返回真

reduce() 和 reduceRight()

reduce方法和reduceRight方法依次處理數(shù)組的每個(gè)成員涕烧,最終累計(jì)為一個(gè)值。它們的差別是汗洒,reduce是從左到右處理(從第一個(gè)成員到最后一個(gè)成員)议纯,reduceRight則是從右到左(從最后一個(gè)成員到第一個(gè)成員),其他完全一樣溢谤。

語(yǔ)法

數(shù)組.reduce( function(數(shù)組上一個(gè)成員,數(shù)組下一個(gè)成員){

},初始值默認(rèn)為0)
//累積求和
var arr = [1, 2, 3, 4, 5];
var sum = arr.reduce(function (a, b) {
  return a + b;
})
console.log( sum );//15

//數(shù)組對(duì)象形式的求和
var data = [
  { id:1,name:'張三',score: 10},
  { id:2,name:'李四',score: 20},
  { id:3,name:'王二',score: 30}
]

var score = data.reduce( function( prev, next ) {
  return prev + next.score;
},0);
console.log( score ); //60

indexOf() 和 lastIndexOf()

數(shù)組也有indexOf方法瞻凤,注意indexOf方法執(zhí)行嚴(yán)格匹配,沒有找到返回-1世杀,返回?cái)?shù)組成員的索引值

var arr = [ 1,'2','A','b'];
console.log( arr.indexOf('1') );// -1 執(zhí)行===操作
console.log( arr.indexOf('2') );// 1 返回?cái)?shù)組成員索引值
console.log( arr.indexOf('a') );// -1 區(qū)分大小寫
console.log( arr.indexOf('b') );// 3 返回索引值

includes es6 返回?cái)?shù)組成員是否包含某個(gè)字符鲫构,若包含返回true,否則返回false

var arr = [ 1,'2','A','b'];
console.log( arr.includes('1') );// false
console.log( arr.includes('2') );// true
console.log( arr.includes('a') );// false
console.log( arr.includes('b') );// true

Array.from 將類數(shù)組轉(zhuǎn)換為真正的數(shù)組

var str = '今天好今熱今玫坛!';

var arr1 = Array.prototype.slice.call( str );
console.log( arr1 );

var arr2 = str.split('');
console.log( arr2 );

var arr3 = Array.from( str );
console.log( arr3 );

new Set() 實(shí)例化一個(gè)類數(shù)組對(duì)象

//將字符串中重復(fù)的字符拋棄,最后返回一個(gè)類數(shù)組對(duì)象
var obj = new Set( str );
console.log( obj );

findIndex 查找數(shù)組的索引值

var data = [
  { id:1, name: '網(wǎng)易', star:'★★★' },
  { id:2, name: '搜狐', star:'★' },
  { id:3, name: '鳳凰網(wǎng)', star:'★★★' }
];

var index = data.findIndex( function( item ){
  return item.id == 2;
})

console.log( index );//1

find 查找數(shù)組的對(duì)應(yīng)成員

var data = [
  { id:1, name: '網(wǎng)易', star:'★★★' },
  { id:2, name: '搜狐', star:'★' },
  { id:3, name: '鳳凰網(wǎng)', star:'★★★' }
];

var item = data.find( function( item ){
  return item.id == 2;
})

console.log( item );//{id: 2, name: "搜狐", star: "★"}

函數(shù)

函數(shù)是一段可以反復(fù)調(diào)用的代碼塊包晰。函數(shù)還能接受輸入的參數(shù)湿镀,不同的參數(shù)會(huì)返回不同的值。

函數(shù)是第一等公民

函數(shù)是本身也是一種值伐憾,類似字符串勉痴、數(shù)值、布爾树肃。

函數(shù)的聲明

  • 語(yǔ)句式聲明
//函數(shù)語(yǔ)句式聲明
function add( a, b ){
  return a+b;
}
  • 表達(dá)式聲明
//函數(shù)表達(dá)式聲明
var add = function( a, b ){
  return a+b;
}
  • 構(gòu)造函數(shù)聲明
var add = new Function( 'a', 'b','return a + b' );

示例

//語(yǔ)句式聲明
function add( a, b ){
  return a+b;
}
console.log( add(1,5) );//6

//表達(dá)式聲明
var add = function( a, b ){
  return a+b;
}
console.log( add(1,5) );//6

//構(gòu)造函數(shù)聲明
var add = new Function( 'a', 'b','return a + b' );
console.log( add(1,5) );//6

語(yǔ)句式聲明和表達(dá)式聲明有什么區(qū)別蒸矛?

  • 語(yǔ)句式聲明會(huì)自動(dòng)提升
//函數(shù)會(huì)自動(dòng)提升,不會(huì)報(bào)錯(cuò)
console.log( add(1,5) ); //6

//語(yǔ)句式聲明
function add( a, b ){
  return a+b;
}

console.log( add(1,5) ); //6
  • 表達(dá)式聲明不提升
//不會(huì)提升胸嘴,致命錯(cuò)誤
console.log( add(1,5) ); //Uncaught TypeError: add is not a function

//表達(dá)式聲明
var add = function( a, b ){
  return a+b;
}
console.log( add(1,5) ); //6

構(gòu)造函數(shù)聲明可以用來(lái)解析字符串表達(dá)式雏掠,類似eval

console.log( eval('5+6*2') );//17

var fn = new Function( 'return 5+6*2' );
console.log( fn() );//17

函數(shù)的重復(fù)聲明

代碼是從上到下執(zhí)行,后面的函數(shù)覆蓋前面的函數(shù)劣像,注意語(yǔ)句式聲明函數(shù)會(huì)提升到代碼頂部

//var 定義 會(huì)覆蓋
var a = '111';
var a = '222';
console.log( a ); //會(huì)覆蓋 222

//let 定義 不會(huì)覆蓋
let b = 'aaa';
let b = 'bbb';

console.log( b );//報(bào)錯(cuò)乡话,重定義錯(cuò)誤

//const 定義 不會(huì)覆蓋
const c = 'true';
const c = 'false';//報(bào)錯(cuò),重定義錯(cuò)誤

//函數(shù) 重定義 會(huì)覆蓋
function add(){
  console.log('hello');
}

var add = function(){
  console.log('您好');
}

function add(){
  console.log('fine');
}

add(); //因?yàn)檎Z(yǔ)句式聲明會(huì)提升耳奕,表達(dá)式不提升绑青,所以輸出您好

圓括號(hào)運(yùn)算符,return 語(yǔ)句和遞歸

  • 圓括號(hào)

調(diào)用函數(shù)時(shí)屋群,要使用圓括號(hào)運(yùn)算符闸婴。圓括號(hào)之中,可以加入函數(shù)的參數(shù)芍躏。

function add(x, y) {
  return x + y;
}

//調(diào)用函數(shù)加圓括號(hào)邪乍,在括號(hào)之中加入?yún)?shù)
add(1, 1) // 2
  • return 語(yǔ)句

return返回并且跳出函數(shù),return是函數(shù)內(nèi)部的語(yǔ)句。

returnbreak的區(qū)別

function echo(){
  for(var i=0;i<10;i++){
    if(i>5){
      return i; //跳出函數(shù)
      break; //跳出循環(huán)
    }
  }
  return 'hello';
}

console.log( echo() ); //6

return 是函數(shù)內(nèi)部語(yǔ)句溺欧,必須有函數(shù)包裹

for( var i=0; i<10; i++ ){
  console.log( i );
  if(i>5){
    return;
  }
}
//報(bào)錯(cuò)喊熟,Uncaught SyntaxError: Illegal return statement
  • 函數(shù)遞歸

函數(shù)可以調(diào)用自身,這就是遞歸姐刁,遞歸一定要有個(gè)結(jié)束值(return)芥牌,不然會(huì)形成死循環(huán)。

//因?yàn)闆]有結(jié)束條件聂使,所以這是一個(gè)死循環(huán)
function fn( n ){
  console.log( n );
  fn( n+1 );
}
fn( 0 );//0 1 2 3 .....

//降序
function desc( n ){
  console.log( n );
  if( n == 0 ) return;
  desc( n-1 );
}

desc( 5 );//5 4 3 2 1 0

//升序
function asc( n ){
  console.log( n );
  if( n == 5 ) return;
  asc( n + 1 );
}

asc( 0 );//0 1 2 3 4 5


//階乘
function fn( n ){
  // console.log( n );
  if( n == 0 ) {
    return 1;
  }else{
    return n * fn( n-1 );
  }
}

//斐波那契數(shù)列
function fib(num) {
  if (num === 0) return 0;
  if (num === 1) return 1;
  return fib(num - 2) + fib(num - 1);
}

fib(6) // 8

函數(shù)是第一等公民

JavaScript 語(yǔ)言將函數(shù)看作一種值壁拉,與其它值(數(shù)值、字符串柏靶、布爾值等等)地位相同弃理。凡是可以使用值的地方,就能使用函數(shù)屎蜓。

  • 可以把函數(shù)賦值給變量
var add = function( a, b){
  return a+b;
}
  • 可以把函數(shù)賦值給對(duì)象的屬性
var obj = {
  name: '張三',
  getAge: function(){
    return 30;
  }
}
  • 可以當(dāng)作參數(shù)傳入其他函數(shù)(作為參數(shù)時(shí)不能加括號(hào))
//1. 將函數(shù)作為參數(shù)痘昌,并提取出來(lái)聲明
function add( a, b ){
  console.log( a ); // function(){ }
  console.log( b ); // 5
  console.log( a() + b );//要加括號(hào) 需要執(zhí)行
}

function fn(){
  return 10;
}

add( fn, 5 );//15

//2. 將函數(shù)作為參數(shù)聲明
function add( a, b ){
  console.log( a() + b );
}

add( function(){
  return 10;
}, 5 );// 15

函數(shù)作為參數(shù)傳入到函數(shù)內(nèi)部,我們也叫這個(gè)函數(shù)(參數(shù))回調(diào)函數(shù)

//仿照數(shù)組實(shí)例forEach
function forEach( arr, fn ){
  for(var i=0;i < arr.length;i++){
    fn( arr[i], i, arr );
  }
}

//調(diào)用
var arr = ['a','b','c','d'];
forEach( arr, function( item, index, arr){
  console.log( item, index, arr );
});

//仿照數(shù)組實(shí)例fliter
function filter( arr, fn ){
  var newArr = [];
  for(var i=0; i < arr.length; i++ ){
    var result = fn( arr[i], i, arr );
    if( result ){
      newArr.push( arr[i] );
    }
  }
  return newArr;
}
var newData = filter( data, function( item, index, arr ){
  return item.name=='張三';
});
console.log( newData );

函數(shù)名的提升

JavaScript 引擎將函數(shù)名視同變量名炬转,所以采用function命令聲明函數(shù)時(shí)辆苔,整個(gè)函數(shù)會(huì)像變量聲明一樣,被提升到代碼頭部扼劈。所以驻啤,下面的代碼不會(huì)報(bào)錯(cuò)。

f();
function f() {}

變量提升

//1
console.log( a ); // 報(bào)錯(cuò)荐吵,未定義


//2
console.log( a ); // undefined
var a;

//3
console.log( a ); // undefined
var a = 10;

//4
console.log( a ); // undefined
var a = 10;
console.log( a ); // 10

變量提升面試題

function foo( x ){
  if( x > 100 ) {
    var tmp = x - 100;
  }
  console.log( tmp ); 
}

foo( 50 ); // undefined

//以上代碼變量會(huì)提升骑冗,等同于
function foo( x ){
  var tmp;
  if( x > 100 ) {
    tmp = x - 100;
  }
  console.log( tmp ); 
}

不能在條件語(yǔ)句中聲明函數(shù)

不要在條件語(yǔ)句是聲明函數(shù),以下寫法不推薦

var foo = false;
if ( foo ) {
  function fn() {
    console.log('hello');
  }
}

fn();//報(bào)錯(cuò) fn is not a function

函數(shù)的屬性和方法

name 屬性

//語(yǔ)句式聲明
function f1() {
}
f1.name // "f1"

//表達(dá)式聲明
var f1 = function add(){
}

f1.name // "add"

遞歸函數(shù)解耦

//遞歸
function desc( n ){
  console.log( n );
  if(n==0)return;
  arguments.callee( n-1 ); // arguments.callee 存在兼容性問題
}
desc( 10 );

//替換上面的方法先煎,兼容性更好
var desc = function fn( n ){
  console.log( n );
  if( n == 0 ) return;
  fn( n-1 );
}
desc( 5 );

length 屬性

函數(shù)的長(zhǎng)度指的是形參的個(gè)數(shù)

function fn( a, b, c, d ){
  console.log( fn.length );
}
console.log( fn.length ); // 4
fn(); // 4

toString() 函數(shù)的toString方法返回一個(gè)字符串遮精,內(nèi)容是函數(shù)的源碼冯事。

function add( a, b ){
  /*
  這是一個(gè)
  多行注釋
  */
  return a+b;
}
console.log( add.toString() );

函數(shù)作用域

作用域(scope)指的是變量存在的范圍

js兩種作用域:

  • 全局作用域(全局變量):

變量在整個(gè)程序中一直存在囚戚,所有地方都可以讀取氮唯,關(guān)閉當(dāng)前窗口,才能釋放內(nèi)存良风。

<script>
var str = '張三';//全局變量
</script>
  • 函數(shù)作用域(局部變量):

變量只在函數(shù)內(nèi)部存在

注意:在函數(shù)內(nèi)部使用var關(guān)鍵字聲明的變量是局部變量

function fn(){
  var str = '李四';
}
fn();
console.log( str ); //報(bào)錯(cuò) str is not defined

注意:在函數(shù)內(nèi)部省略var關(guān)鍵字谊迄,會(huì)自動(dòng)提升為全局變量。

function fn(){
  str = '李四';
}
fn();
console.log( str ); // 李四

<script>
var str = '張三';//全局變量
function fn(){
  var age = 20; //局部變量
}
</script>

變量提升面試題 1

fn(); // undefined 20

var str = '張三'; 
function fn(){
  var age = 20;
  console.log( str, age);
}


變量提升面試題 2

function fn(){
  if ( false ) {
    var x = 5;
  }
  console.log(x); 
}

fn(); // undefined

變量提升面試題 3

//代碼從上到下執(zhí)行
function x(){
  console.log(a);
  a = 10;
}
x();
console.log( a ); // Uncaught ReferenceError: a is not defined

變量提升面試題 4

function x(){
  console.log(a);
  var a = 10;
}
x(); // undefined
console.log( a ); // Uncaught ReferenceError: a is not defined

函數(shù)作用域面試題 1

var str = '張三'; 
function fn(){
  var age = 20;
  var str = '李四';
  console.log( str, age);
}

fn(); // 李四 20

console.log( str ); // 張三

函數(shù)作用域面試題 2

var str = '張三'; 
function fn(){
  var age = 20;
  str = '李四';
  console.log( str, age);
}

fn(); // 李四 20

console.log( str ); // 李四

函數(shù)作用域面試題 3

function one( ){

  var str = '張三';
  function two(){
    var age = 20;
    console.log( str );
  }
  two();

  console.log( age );

}

one(); // 報(bào)錯(cuò) 

函數(shù)本身的作用域

函數(shù)本身也是一個(gè)值烟央,也有自己的作用域统诺。它的作用域與變量一樣,就是其聲明時(shí)所在的作用域疑俭,與其運(yùn)行時(shí)(調(diào)用時(shí))所在的作用域無(wú)關(guān)粮呢。

情況 1

var a = 1;
//聲明時(shí)作用域
var x = function(){
  console.log(a);
}

function f() {
  var a = 2;
  //運(yùn)行時(shí)(調(diào)用時(shí))作用域
  x();
}

f();//1

情況 2

var a = 1;
//聲明時(shí)作用域
var x = function(){
  var a = 5;
  console.log(a);
}

function f() {
  var a = 2;
  //運(yùn)行時(shí)(調(diào)用時(shí))作用域
  x();
}

f();//5

情況 3

//聲明時(shí)作用域
var x = function(){
  console.log(a);
}

function f() {
  var a = 2;
  //運(yùn)行時(shí)(調(diào)用時(shí))作用域
  x();
}

f(); // a is not defined

情況 4

//聲明時(shí)作用域
var x = function(){
  console.log(a);
  a = 10;
  //注意沒有使用var關(guān)鍵字 則沒有優(yōu)先提升權(quán)限
}

function f() {
  var a = 2;
  //運(yùn)行時(shí)(調(diào)用時(shí))作用域
  x();
}

f(); // Uncaught ReferenceError: a is not defined

函數(shù)閉包

在函數(shù)內(nèi)部返回函數(shù),返回的函數(shù)調(diào)用了父函數(shù)的局部變量,這樣形成了閉包啄寡。

  • 閉包可以將函數(shù)內(nèi)部的局部變量暴露給外部豪硅,是函數(shù)內(nèi)部和外部的橋梁
  • 閉包會(huì)導(dǎo)致函數(shù)內(nèi)部的局部變量無(wú)法釋放,不被垃圾回收站回收挺物。

閉包的缺點(diǎn):閉包因?yàn)闀?huì)使局部變量?jī)?nèi)存無(wú)法及時(shí)釋放懒浮,如果使用太多會(huì)增加內(nèi)存開銷,帶來(lái)性能隱患识藤。

function one(){
  var name = '張三';
  function two(){
    console.log( name );
  }
  return two;
}

var fn = one();
fn();

閉包經(jīng)典面試題 1

function bb(){
  var num = 999;
  return function(){
    num++;
    console.log( num );
  }
}

var fun = bb();// function(){}
fun(); // 1000
fun(); // 1001

參數(shù)

函數(shù)運(yùn)行的時(shí)候砚著,有時(shí)需要提供外部數(shù)據(jù),不同的外部數(shù)據(jù)會(huì)得到不同的結(jié)果痴昧,這種外部數(shù)據(jù)就叫參數(shù)稽穆。

function square(x) {
  return x * x;
}

參數(shù)可以省略,從后向前省略赶撰,形參和實(shí)際參數(shù)一一對(duì)應(yīng)舌镶。

運(yùn)行時(shí)無(wú)論提供多少個(gè)參數(shù),或者不提供參數(shù)都不會(huì)報(bào)錯(cuò)豪娜,省略的參數(shù)值是undefined

函數(shù)的length只和形式參數(shù)個(gè)數(shù)有關(guān)乎折,和實(shí)際參數(shù)無(wú)關(guān)

沒有辦法只省略靠前的參數(shù),而保留靠后的參數(shù)侵歇,從后向前省略。

形參的作用域是函數(shù)作用域吓蘑,也就是局部變量

//1 使用條件語(yǔ)句
function add( a, b, c){
  if(a==undefined) a =0;
  if(b==undefined) b =0;
  if(c==undefined) c =0;
  return a + b + c;
}

console.log(  add( 1, 2 ) );

//2 使得短路法則
function add( a, b, c){
  a = a || 0;
  b = b || 0;
  c = c || 0;
  return a + b + c;
}

console.log(  add( 1, 2 ) );

//3 默認(rèn)參數(shù) es6
function add( a = 0, b = 0, c = 0){
  return a + b + c;
}
console.log(  add( 1, 2 ) );

函數(shù)參數(shù)傳遞方式
  • 參數(shù)為原始類型(數(shù)值惕虑、字符串、布爾磨镶、undefined溃蔫、null)傳遞方式是傳值傳遞。
  • 參數(shù)為引用類型(對(duì)象琳猫、數(shù)組)傳遞方式是傳址傳遞伟叛。

比較下面兩道題,注意區(qū)分:

//函數(shù)內(nèi)部沒有加var關(guān)鍵字脐嫂,認(rèn)為全局變量
var p = 2;
function f() {
  p = 3;
}
f();
console.log( p );//3

//因?yàn)閜是形參统刮,而它是直接拷貝 2,內(nèi)部覆蓋它的值為3 不會(huì)影響到全局變量p
var p = 2;
function f( p ) {
  p = 3;
}
f( p );
console.log( p );//2

數(shù)組是傳址傳遞账千,所以在數(shù)組內(nèi)部會(huì)影響到外面?zhèn)魅氲臄?shù)組

var arr = ['蘋果','桔子'];
function f( arr ) {
  arr[1] = '香蕉';
}
f( arr );
console.log( arr );//['蘋果','香蕉']

解決辦法侥蒙,就是復(fù)制一個(gè)新數(shù)組

//使用es6擴(kuò)展運(yùn)算符生成新數(shù)組
var arr = ['蘋果','桔子'];
function f( [...arr] ) {
  arr[1] = '香蕉';
}
f( arr );
console.log( arr );//['蘋果','桔子']

//使用concat生成新數(shù)組
var arr = ['蘋果','桔子'];
function f( arr ) {
  arr = [].concat( arr );
  arr[1] = '香蕉';
}
f( arr );
console.log( arr );//['蘋果','桔子']


對(duì)象因?yàn)橐彩且妙愋停性诤瘮?shù)內(nèi)部修改對(duì)象時(shí)會(huì)改變外面的對(duì)象

var obj = {
  name: '張三',
  info: {
    age: 20
  }
};

function f( obj ) {
  obj.info.age = 30;
}
f( obj );
console.log( obj );//年齡會(huì)被該成30


同名參數(shù)

如果有同名的參數(shù)匀奏,則取最后出現(xiàn)的那個(gè)值鞭衩。

即使后面的a沒有值或被省略,也是以其為準(zhǔn)。

function f(a, a) {
  console.log(a);
}

f(1, 2) // 2

arguments 參數(shù)集合對(duì)象

由于 JavaScript 允許函數(shù)有不定數(shù)目的參數(shù)论衍,所以需要一種機(jī)制瑞佩,可以在函數(shù)體內(nèi)部讀取所有參數(shù)。這就是arguments對(duì)象的由來(lái)坯台。

arguments 是一個(gè)類數(shù)組對(duì)像炬丸,它包含了數(shù)組所有參數(shù)。

arguments 對(duì)象包含了函數(shù)運(yùn)行時(shí)的所有參數(shù)(實(shí)際參數(shù))

arguments.callee 指向的是函數(shù)本身

function max(){
  var args = arguments;
  var arr = [];

  if( args.length > 1 ){
    arr = Array.from( args );
  }else{
    if( typeof args[0] =='string' ){
      arr = args[0].split('');
    }else{
      arr = args[0];
    }
  }

  arr = arr.filter(function(item){
    return isNaN(item) == false;
  })

  var max = arr[0];
  for(var i=0;i<arr.length;i++){
    if ( max < arr[i] ) max = arr[i];
  }
  console.log( max );

}

max('230a1'); 
max(2,'a',30,1);
max([2,'a',13,1]);

經(jīng)典面試題:多種辦法單擊獲取索引值

<ul>
    <li>首頁(yè)</li>
    <li>關(guān)于我們</li>
    <li>產(chǎn)品中心</li>
</ul>
<script>
var lis = document.querySelectorAll('li');

//1. es6 塊級(jí)作用域?qū)崿F(xiàn)
for(let i = 0; i < lis.length; i++ ){
  lis[i].onclick = function(){
    console.log( i );
  }
}

//2.將索引值緩存到對(duì)象上捂人,然后再到對(duì)象自身去取
for(var i = 0; i < lis.length; i++ ){
  lis[i].index = i;
  lis[i].onclick = function(){
    console.log( this.index );
  }
}

//3. 使用閉包來(lái)緩存索引值
for(var i = 0; i < lis.length; i++ ){
  function fn( j ){
    lis[j].onclick = function(){
      console.log( j );
    }
  }
  fn( i );
}

//4. 使用數(shù)組的indexOf方法獲取索引值
var arr = Array.from( lis );
for(var i = 0; i < lis.length; i++ ){
  lis[i].onclick = function(){
    console.log( arr.indexOf( this ) );
  }
}
</script>

立即調(diào)用的函數(shù)表達(dá)式 IIFE

圓括號(hào)()是一種運(yùn)算符御雕,跟在函數(shù)名之后,表示調(diào)用該函數(shù)滥搭。

比如酸纲,print()就表示調(diào)用print函數(shù)。

!function () { /* code */ }();
~function () { /* code */ }();
-function () { /* code */ }();
+function () { /* code */ }();

//官方建議
( function(){ /* code */ } )();
( function(){ /* code */ }() );

示例

+function( a, b ){
  console.log(a+b);
}(2,3);

(function( a, b ){
  console.log(a+b);
})(2,3);

(function( a, b ){
  console.log(a+b);
}(2,3));

立即執(zhí)行函數(shù)用途:

  • 不必為函數(shù)命名瑟匆,避免了污染全局變量
  • IIFE內(nèi)部形成了一個(gè)單獨(dú)的作用域闽坡,可以封裝一些外部無(wú)法讀取的私有變量

用js寫原生插件或者組件,我們習(xí)慣用IIFE封裝它愁溜,避免污染全局變量疾嗅。

(function(){

  var iAlert = function(){
    console.log('我是警告框插件!');
  }

  //將私有的變量注冊(cè)為全局變量
  window.iAlert = iAlert;

}());

//調(diào)用插件
iAlert();

定義組件時(shí)冕象,組件默認(rèn)參數(shù)通常采用覆蓋替換法實(shí)現(xiàn)

//默認(rèn)參數(shù)
var oldObj = {
  page: 1,
  perpage: 5
}

//用戶參數(shù)
var newObj = {
  page: 3,
  perpage: 10
}

//合并默認(rèn)參數(shù)和用戶參數(shù)
var obj = Object.assign( {}, oldObj, newObj);
// var obj = { ...oldObj, ...newObj };
console.log( obj );

js 嚴(yán)格模式

默認(rèn)是比較寬松的模式

如何設(shè)置嚴(yán)格模式代承?

全局設(shè)置

<script>
//設(shè)置嚴(yán)格模式
'use strict'

</script>

函數(shù)內(nèi)設(shè)置

<script>
//函數(shù)內(nèi)設(shè)置嚴(yán)格模式
function fn(){
  'use strict'

}
</script>

嚴(yán)格模式有那些要求(部分)?

  1. 聲明變量需要使用關(guān)鍵字var渐扮、let论悴、const,否則報(bào)錯(cuò)
'use strict'
str = '張三';
console.log(str); //報(bào)錯(cuò)

  1. 不允許函數(shù)的形參重名
'use strict'
function x(p1, p1) {
} //報(bào)錯(cuò)

  1. 不允許刪除一個(gè)不允許刪除的屬性
'use strict';
delete Object.prototype; //錯(cuò)誤

  1. 變量名不能使用 arguments 字符串
'use strict';
var arguments = 10;
console.log( arguments );

  1. 由于一些安全原因墓律,在作用域 eval() 創(chuàng)建的變量不能被調(diào)用
'use strict';
eval ('var x = 2');
alert (x); 

  1. 禁止this關(guān)鍵字指向全局對(duì)象膀估。
'use strict';
function fn(){
  console.log(this);
}

fn();//本來(lái)是指向windows,但在嚴(yán)格模式下不允許耻讽,返回undefined

  1. 不允許刪除變量或?qū)ο蟆?/li>
'use strict';
var x = 3.14;
delete x; 

使用new Function 將字符串當(dāng)作命令執(zhí)行察纯。

語(yǔ)法

new Function('參數(shù)1','參數(shù)2','...','函數(shù)內(nèi)部返回');

最后一個(gè)參數(shù)始終是函數(shù)內(nèi)部返回代碼

var jsonp = 'foo({"id": 42})';

// foo是函數(shù)的參數(shù),它是一個(gè)函數(shù)(回調(diào)函數(shù))针肥。
var f = new Function( 'foo', jsonp );

// 相當(dāng)于定義了如下函數(shù) 
// function f(foo) {
//   foo({"id":42}); //回調(diào)函數(shù)
// }

//調(diào)用 
f(function (json) {
  console.log( json.id ); // 42
})

jsonp原理

為了便于客戶端使用數(shù)據(jù)(比如遠(yuǎn)程數(shù)據(jù))饼记,逐漸形成了一種非正式傳輸協(xié)議,進(jìn)行數(shù)據(jù)傳送慰枕,這種方式我們叫JSONP跨域握恳,該協(xié)議的一個(gè)要點(diǎn)就是允許服務(wù)端返回一個(gè)回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)包裹這數(shù)據(jù)捺僻,這樣客戶端就可以方便的取到服務(wù)器返回的數(shù)據(jù)乡洼。

jsonp主要原理是利用js回調(diào)函數(shù)機(jī)制實(shí)現(xiàn)一種非正式跨域崇裁。

  • 遠(yuǎn)程服務(wù)端返回一個(gè)函數(shù),該函數(shù)包裹數(shù)據(jù)
//服務(wù)端
//假設(shè)以下 http://www.jx-tongan.com/vueapi/hello.js 的內(nèi)容
fn({
  name:'張三',
  age: 20,
  habby: ['釣魚','游泳']
});

  • 客戶端通過回調(diào)函數(shù)的形參獲取到服務(wù)端返回的數(shù)據(jù)
<script>
//客戶端
//服務(wù)端的數(shù)據(jù)在形參obj上 
function city( obj ){
  console.log( obj );
}  
</script>

<script src="js/city.js"></script>

運(yùn)算符

算術(shù)運(yùn)算符

  • 指數(shù)運(yùn)算符(注意兼容性)
console.log( 2 ** 2 );// 4
console.log( 2 ** 3 );// 8

  • 取余
console.log( 10 % 3); // 1
console.log( 13 % 6); // 1
  • 自增運(yùn)算符

注意下面代碼的區(qū)別

//示例 1 
var a = 0;
var b = 0;
a++;
++b;
console.log( a, b ); //1 1

//示例 2
var x = 0;
var y = 0;

console.log( x++, ++y ); //0 1

賦值運(yùn)算符

最常見的賦值運(yùn)算符,當(dāng)然就是等號(hào)(=)束昵。

var x = 1;
var x = y;

賦值運(yùn)算符還可以與其他運(yùn)算符結(jié)合拔稳,形成變體

// 等同于 x = x + y
x += y

// 等同于 x = x - y
x -= y

// 等同于 x = x * y
x *= y

// 等同于 x = x / y
x /= y

// 等同于 x = x % y
x %= y

// 等同于 x = x ** y
x **= y

比較運(yùn)算符

提供了8個(gè)比較運(yùn)算符:

  • < 小于運(yùn)算符
  • > 大于運(yùn)算符
  • <= 小于或等于運(yùn)算符
  • >= 大于或等于運(yùn)算符
  • == 相等運(yùn)算符
  • === 嚴(yán)格相等運(yùn)算符
  • != 不相等運(yùn)算符
  • !== 嚴(yán)格不相等運(yùn)算符

字符串按照字典順序進(jìn)行比較。

'cat' > 'dog' // false
'cat' > 'catalog' // false
'大' > '小' // false

上面代碼中锹雏,“大”的 Unicode 碼點(diǎn)是22823巴比,“小”是23567,因此返回false礁遵。

兩個(gè)原始類型的值的比較轻绞,除了相等運(yùn)算符(==)和嚴(yán)格相等運(yùn)算符(===),其他比較運(yùn)算符都是先轉(zhuǎn)成數(shù)值再比較佣耐。

+0 === -0 // true

{} === {} // false
[] === [] // false
(function () {} === function () {}) // false

new Date() > new Date() // false
new Date() < new Date() // false
new Date() === new Date() // false

NaN === NaN  // false

undefined === undefined // true
null === null // true


false == null // false
false == undefined // false

0 == null // false
0 == undefined // false

undefined == null // true

相等運(yùn)算符隱藏的類型轉(zhuǎn)換政勃,會(huì)帶來(lái)一些違反直覺的結(jié)果。

0 == ''             // true
0 == '0'            // true

2 == true           // false
2 == false          // false

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true

上面這些表達(dá)式都很容易出錯(cuò)兼砖,因此不要使用相等運(yùn)算符(==)奸远,最好只使用嚴(yán)格相等運(yùn)算符(===)。

布爾運(yùn)算符

  • !:取反運(yùn)算符
  • &&:且運(yùn)算符
  • ||:或運(yùn)算符
  • ?::三元運(yùn)算符

取反運(yùn)算符是一個(gè)感嘆號(hào)讽挟,用于將布爾值變?yōu)橄喾粗道僚眩?code>true變成falsefalse變成true耽梅。

用取反來(lái)寫開關(guān)效果

<button id="btn">按鈕</button>
<script>
var flag = false;
document.getElementById('btn').onclick = function(){
  flag = !flag;
  console.log(flag);
}
</script>

!! 相當(dāng)于使用Boolean轉(zhuǎn)換為布爾類型

!!x
// 等同于
Boolean(x)

示例

var str = '111';
console.log( Boolean( str ) );//true
console.log( !!str );//true

且運(yùn)算符(&&)

它的運(yùn)算規(guī)則是:

  • 如果第一個(gè)運(yùn)算符的布爾值為true薛窥,那么返回第二個(gè)運(yùn)算符的值。
  • 如果第一個(gè)運(yùn)算符的布爾值為false眼姐,那么返回第一個(gè)運(yùn)算符的值诅迷。
true && 'hello'; // hello
false && 'hello'; // false

'張三' && 20; // 20
'0' && 'ab'; // ab
0 && 'ab'; // 0
1>2 && ''; // false
'' && 'ab'; // ''

1 && 0 && 'ab'; // 0
'a' && 'null' && 0; // 0

var age = 20;
if( age > 18 ) console.log('成年!');
console.log( age > 18 && '成年!' );

或運(yùn)算符(||)

它的運(yùn)算規(guī)則是:

  • 如果第一個(gè)運(yùn)算符的布爾值為true妥凳,那么返回第一個(gè)運(yùn)算符的值。
  • 如果第一個(gè)運(yùn)算符的布爾值為false答捕,那么返回第二個(gè)運(yùn)算符的值逝钥。
true || 'ab'; // true
false || 'ab'; // ab
'false' || 'ab'; // false
0 || null; // null
'' || 0 || null || 'ab'; // ab
'ab' || null || 0; // ab

且運(yùn)算:遇真返回第2個(gè)值,遇假直接輸出假拱镐。
或運(yùn)算:遇假返回第2個(gè)值艘款,遇真直接輸出真。

//且運(yùn)算:遇真返回第2個(gè)值沃琅,遇假直接輸出假哗咆。
//或運(yùn)算:遇假返回第2個(gè)值,遇真直接輸出真益眉。

var str1 = 'he' && '0' && [] || 20 || {};
console.log( str1 );// []

var str2 = 'he' && '0' && '' || 0 || {};
console.log( str2 );// {}

用且或來(lái)替代條件語(yǔ)句

if (i) {
  doSomething();
}

// 等價(jià)于

i && doSomething();

三元條件運(yùn)算符

語(yǔ)法

console.log( true ? '真' : '假');

't' ? 'hello' : 'world' // "hello"
0 ? 'hello' : 'world' // "world"

void 運(yùn)算符

void運(yùn)算符的作用是執(zhí)行一個(gè)表達(dá)式晌柬,然后不返回任何值姥份,或者說(shuō)返回undefined

console.log( 3*5 ); // 15
console.log( void(3*5) ); // undefined

阻止超級(jí)鏈接默認(rèn)事件

<div style="height:2000px;"></div>

<a href="javascript:void(0)">連接1</a>
<a href="javascript:;">連接2</a>
<a>連接3</a>

逗號(hào)運(yùn)算符

逗號(hào)運(yùn)算符用于對(duì)兩個(gè)表達(dá)式求值年碘,并返回后一個(gè)表達(dá)式的值澈歉。

注意要加上括號(hào),不然會(huì)報(bào)錯(cuò)

var str1 = ( 2+4, 3*5 );
console.log( str ); //15

var str2 = ( a = 2+4, a + 3*5 );
console.log( str );//21

var str3 = ( a = 2+4, 3*5 );
console.log( a, str ); //6 15

錯(cuò)誤處理

JavaScript 解析或運(yùn)行時(shí)屿衅,一旦發(fā)生錯(cuò)誤埃难,引擎就會(huì)拋出一個(gè)錯(cuò)誤對(duì)象,JavaScript 原生提供Error構(gòu)造函數(shù)涤久,所有拋出的錯(cuò)誤都是這個(gè)構(gòu)造函數(shù)的實(shí)例涡尘。

創(chuàng)建錯(cuò)誤對(duì)象實(shí)例

var err = new Error('出錯(cuò)了');
err.message // "出錯(cuò)了"

try catch 錯(cuò)誤捕獲語(yǔ)句,它將語(yǔ)句在沙箱中運(yùn)行响迂,在語(yǔ)句中可以拋出錯(cuò)誤考抄。避免發(fā)送致命錯(cuò)誤,導(dǎo)致語(yǔ)句中斷無(wú)法繼續(xù)栓拜。

//錯(cuò)誤捕獲
try {
  if(!document.getElementById('box1')){
    throw new Error('錯(cuò)誤:不存在的對(duì)象座泳!');
  }
  document.getElementById('box1').innerText='錯(cuò)誤代碼演示';
} catch( e ) {
  //e 是錯(cuò)誤對(duì)象
  console.dir(e);
} finally {
    console.log('無(wú)論對(duì)錯(cuò)都會(huì)執(zhí)行');
}

console.log('代碼繼續(xù)執(zhí)行');

js錯(cuò)誤類型

  • SyntaxError: 語(yǔ)法錯(cuò)誤
// 1. Syntax Error: 語(yǔ)法錯(cuò)誤
// 1.1 變量名不符合規(guī)范
var 1       // Uncaught SyntaxError: Unexpected number
var 1a       // Uncaught SyntaxError: Invalid or unexpected token
// 1.2 給關(guān)鍵字賦值
function = 5     // Uncaught SyntaxError: Unexpected token =

  • Uncaught ReferenceError: 引用錯(cuò)誤

引用一個(gè)不存在的變量時(shí)發(fā)生的錯(cuò)誤
將一個(gè)值分配給無(wú)法分配的對(duì)象,比如對(duì)函數(shù)的運(yùn)行結(jié)果或者函數(shù)賦值幕与。

// 2.1 引用了不存在的變量
a()       // Uncaught ReferenceError: a is not defined
console.log(b)     // Uncaught ReferenceError: b is not defined
// 2.2 給一個(gè)無(wú)法被賦值的對(duì)象賦值
console.log("abc") = 1   // Uncaught ReferenceError: Invalid left-hand side in assignment

  • RangeError: 范圍錯(cuò)誤
// 3.1 數(shù)組長(zhǎng)度為負(fù)數(shù)
[].length = -5      // Uncaught RangeError: Invalid array length
// 3.2 Number對(duì)象的方法參數(shù)超出范圍
var num = new Number(12.34)
console.log(num.toFixed(-1))   // Uncaught RangeError: toFixed() digits argument must be between 0 and 20 at Number.toFixed
// 說(shuō)明: toFixed方法的作用是將數(shù)字四舍五入為指定小數(shù)位數(shù)的數(shù)字,參數(shù)是小數(shù)點(diǎn)后的位數(shù),范圍為0-20.

  • TypeError 類型錯(cuò)誤
    變量或參數(shù)不是預(yù)期類型時(shí)發(fā)生的錯(cuò)誤挑势。比如使用new字符串、布爾值等原始類型和調(diào)用對(duì)象不存在的方法就會(huì)拋出這種錯(cuò)誤啦鸣,因?yàn)閚ew命令的參數(shù)應(yīng)該是一個(gè)構(gòu)造函數(shù)潮饱。
// 4.1 調(diào)用不存在的方法
123()        // Uncaught TypeError: 123 is not a function
var o = {}
o.run()        // Uncaught TypeError: o.run is not a function
// 4.2 new關(guān)鍵字后接基本類型
var p = new 456      // Uncaught TypeError: 456 is not a constructor

  • URIError,URL 錯(cuò)誤
    主要是相關(guān)函數(shù)的參數(shù)不正確诫给。
decodeURI("%")     // Uncaught URIError: URI malformed at decodeURI

URI相關(guān)參數(shù)不正確時(shí)拋出的錯(cuò)誤香拉,主要涉及encodeURI、decodeURI()中狂、encodeURIComponent()凫碌、decodeURIComponent()、escape()和unescape()六個(gè)函數(shù)胃榕。

  • EvalError eval() 函數(shù)執(zhí)行錯(cuò)誤
    在ES5以下的JavaScript中盛险,當(dāng)eval()函數(shù)沒有被正確執(zhí)行時(shí),會(huì)拋出evalError錯(cuò)誤勋又。
var myEval = eval;
myEval("alert('call eval')");

編程風(fēng)格

縮進(jìn)

縮進(jìn)建議統(tǒng)一使用空格(1個(gè)tab=2個(gè)空格苦掘,1個(gè)tab=4個(gè)空格),因?yàn)椴煌僮飨到y(tǒng)對(duì)tab解析不不太一樣楔壤。

//bad
function fn(){
if(1==1){
console.log('aaa');
}else{
console.log('bbb');
}
}

//good
function fn(){
  if(1==1){
    console.log('aaa');
  }else{
    console.log('bbb');
  }
}

區(qū)塊

建議總是使用大括號(hào)表示區(qū)塊

function fn()
{

}

//well
function fn() {

}

圓括號(hào)

  • 函數(shù)的調(diào)用
// 表示函數(shù)定義時(shí)鹤啡,函數(shù)名與左括號(hào)之間沒有空格。

//bad
function add () {
}
//good
function add() {
}

//表示函數(shù)調(diào)用時(shí)蹲嚣,函數(shù)名與左括號(hào)之間沒有空格递瑰。
//bad
add()

//good
add();

// 其他情況時(shí)祟牲,前面位置的語(yǔ)法元素與左括號(hào)之間,都有一個(gè)空格泣矛。

//bad
foo (bar);
return(a+b);
if(a === 0) {...}
function foo (b) {...}
function(x) {...}

//good
foo(bar);
return (a+b);
if (a === 0) {...}
function foo(b) {...}
function (x) {...}

不使用分號(hào)的情況

以下三種情況不需要添加分號(hào)

for 和 while 循環(huán)

for ( ; ; ) {
} // 沒有分號(hào)

while (true) {
} // 沒有分號(hào)

注意疲眷,do...while循環(huán)是有分號(hào)的。

do {
  a--;
} while(a > 0); // 分號(hào)不能省略

分支語(yǔ)句:if您朽,switch狂丝,try

if (true) {
} // 沒有分號(hào)

switch () {
} // 沒有分號(hào)

try {
} catch {
} // 沒有分號(hào)

函數(shù)的聲明語(yǔ)句

function f() {
} // 沒有分號(hào)

注意,函數(shù)表達(dá)式仍然要使用分號(hào)哗总。s

var f = function f() {
};

自動(dòng)添加分號(hào)

雖然大部分語(yǔ)法會(huì)自動(dòng)加上分號(hào)几颜,但是也存在一些解析歧義,比如分號(hào)不能正確的加入合適的位置讯屈,建議手動(dòng)加上分號(hào)蛋哭。

全局變量

JavaScript 最大的語(yǔ)法缺點(diǎn),可能就是全局變量對(duì)于任何一個(gè)代碼塊涮母,都是可讀可寫谆趾。這對(duì)代碼的模塊化和重復(fù)使用,非常不利叛本。

因此沪蓬,建議避免使用全局變量。
如果不得不使用来候,可以考慮用大寫字母表示變量名

var CPAGE = 5;

相等和嚴(yán)格相等

推薦使用 === 代替 ==

自增和自減運(yùn)算符

//bad
++x

//good
x += 1;

改用+= 1跷叉,代碼變得更清晰了。

建議自增(++)和自減(--)運(yùn)算符盡量使用+=-=代替营搅。

switch...case 結(jié)構(gòu)

function doAction( action ) {
  switch (action) {
    case 'hack':
      return 'hack';
      break;
    case 'slash':
      return 'slash';
      break;
    case 'run':
      return 'run';
      break;
    default:
      throw new Error('Invalid action.');
  }
}

上面的代碼建議改寫成對(duì)象結(jié)構(gòu)云挟。

function doAction(action) {
  var actions = {
    'hack': function () {
      return 'hack';
    },
    'slash': function () {
      return 'slash';
    },
    'run': function () {
      return 'run';
    }
  };

  if (typeof actions[action] !== 'function') {
    throw new Error('Invalid action.');
  }

  return actions['run']();
}

因此,建議switch...case結(jié)構(gòu)可以用對(duì)象結(jié)構(gòu)代替转质。

Math對(duì)象

該對(duì)象不是構(gòu)造函數(shù)园欣,不能生成實(shí)例。

var a = 2.67;

//報(bào)錯(cuò)休蟹,Math對(duì)象不是構(gòu)造函數(shù)
var str = new Math();
str.round( a );

// 應(yīng)該這樣寫
var str = Math.round( a );//3

靜態(tài)屬性

  • Math.PI:圓周率
  • Math.SQRT2:2 的平方根

這些屬性都是只讀的沸枯,不能修改。

靜態(tài)方法

  • Math.abs():絕對(duì)值
console.log( Math.abs(-1) );//1
console.log( Math.abs(1) );//1

  • Math.ceil():上舍入
console.log( Math.ceil(3.00001) ); //4
console.log( Math.ceil(3.99999) ); //4
console.log( Math.ceil(3.33333) ); //4

  • Math.floor():下舍入
console.log( Math.floor(3.99999) ); //3
console.log( Math.floor(3.00001) ); //3
console.log( Math.floor(3.33333) ); //3

  • Math.round():四舍五入
console.log( Math.round(3.99999) ); //4
console.log( Math.round(3.00001) ); //3
console.log( Math.round(3.33333) ); //3

  • Math.max():最大值
console.log( Math.max(2,1,5,6,7) );// 7
console.log( Math.max.apply( null, [2,1,5,6,7] ) ); // 7

  • Math.min():最小值
console.log( Math.min(2,1,5,6,7) );// 1
console.log( Math.min.apply( null, [2,1,5,6,7] ) ); // 1

  • Math.pow():指數(shù)運(yùn)算

語(yǔ)法:

Math.pow(底數(shù),指數(shù));

console.log( 2 ** 3 ); //8
console.log( Math.pow(2,3 ) );//8

  • Math.sqrt():平方根
// 2的平方根
console.log( Math.SQRT2 );//1.4142135623730951
console.log( Math.sqrt(2) );//1.4142135623730951
console.log( Math.sqrt(4) ); //2

  • Math.random():隨機(jī)數(shù)

返回0~1之間鸡挠,可能等于0辉饱,但是一定小于1搬男。

console.log( Math.random() );

//隨機(jī) 0 - 10 之間的整數(shù)
console.log( Math.round( Math.random() * 10 ) );

//隨機(jī) 5 - 15 之間的整數(shù)
console.log( 5 + Math.round( Math.random() * 10 ) );

//隨機(jī)取出數(shù)組成員(數(shù)組可增可減)
var arr = ['蘋果','桔子','菠蘿'];
var index =  Math.floor( Math.random() * arr.length );//0 - 2
console.log( arr[index] );


//隨機(jī)打亂一個(gè)數(shù)組
var arr = [1,2,3,4,5,6,7,8,9];
arr.sort(function(){
  return 0.5 - Math.random();
})
console.log( arr );

setTimeout 單次定時(shí)執(zhí)行函數(shù)

語(yǔ)法:

  • fn:函數(shù)
  • str:字符串
  • time:時(shí)間毫秒(1000毫秒=1秒)
setTimeout( fn|str,time);

示例

//寫法一
setTimeout(function(){
  console.log('hello');
},1000);

//寫法二
function echo(){
  console.log('hello');
}
setTimeout( echo, 1000);
setTimeout('echo()',2000);

  • 有時(shí)候可以用setTimeout模擬異步操作
//打開文件
console.log('正在打開文件...');
setTimeout(function(){
  console.log('文件已打開拣展!');
},3000);
console.log('hello');

// 執(zhí)行先后順序如下:
//1.正在打開文件...
//2.hello
//3.文件已打開!

  • 延時(shí)操作
setTimeout(function(){
  console.log('暫停3秒');
},3000);

setTimeout對(duì)象

setTimeout(function(){
  console.log('ok');
},0);

console.log('hello');

//輸出順序是 hello > ok

經(jīng)典面試題1

for(var i=0;i<10;i++){

  setTimeout(function(){
    console.log(i);
  },0)

}

//輸出10次 10

經(jīng)典面試題2

for(let i=0;i<10;i++){
  console.log('a:',i);
  setTimeout(function(){
    console.log('b:',i);
  },0)

}
//輸出 a: 0 ~ 9
//輸出 b: 0 ~ 9

  1. 如果需要手動(dòng)寫動(dòng)畫缔逛,你認(rèn)為最小時(shí)間間隔是多久备埃,為什么姓惑?

答:多數(shù)顯示器默認(rèn)頻率是60Hz,即1秒刷新60次按脚,所以理論上最小間隔為1/60*1000ms16.7ms

clearTimeout 清除單次操作定時(shí)器
<button id="btn">清除定時(shí)</button>
<script>
var time = setTimeout(function(){
  console.log('hello');
},5000);

document.getElementById('btn').onclick = function(){
  clearTimeout( time );
  alert('清除完畢于毙!');
}
</script>

setInterval 多次定時(shí)執(zhí)行函數(shù)

語(yǔ)法:

  • fn:函數(shù)
  • str:字符串
  • time:時(shí)間毫秒(1000毫秒=1秒)
setInterval( fn|str,time);

示例

setInterval(function(){
  console.log('hello');
},1000)
clearInterval 清除多次定時(shí)執(zhí)行函數(shù)

簡(jiǎn)單的隨機(jī)點(diǎn)名效果

  <h1 id="user"></h1>
  <button id="addbtn">添加</button>
  <button id="btn">啟動(dòng)</button>

<script>
var list = [];
if( localStorage.getItem('list') ){
  list = localStorage.getItem('list').split(',');
}

function play(){

  var num = 3;
  var user = document.getElementById('user');
  if(list.length == 1){
    user.innerHTML = list[0];
    return;
  }
  var int = setInterval(function(){

    user.innerText = num;
    num -= 1;
    if(num < 0) {
      clearInterval( int );
      var index = Math.floor(Math.random() * list.length);
      user.innerText = list[index];
      list.splice(index,1);
      console.log(list);
    }
    
  },1000);

}

document.getElementById('addbtn').onclick = function(){
  var str = prompt('請(qǐng)輸入姓名!');
  list.push( str );

  //本地存儲(chǔ)
  localStorage.setItem('list', list.toString() );
}

document.getElementById('btn').onclick = function(){

  //啟動(dòng)隨機(jī)點(diǎn)名
  play();

}


</script>

Date對(duì)象

時(shí)間起點(diǎn)

它以19701100:00:00作為時(shí)間的零點(diǎn)辅搬,可以表示的時(shí)間范圍是前后各1億天(單位為毫秒)唯沮。

時(shí)間最小單位

毫秒,換算 1000毫秒 = 1

普通函數(shù)的用法

console.log( Date() );
//Tue Jul 30 2019 14:17:35 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間)

console.log( Date(2000, 1, 1) );
//Tue Jul 30 2019 14:17:35 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間)

上面代碼說(shuō)明堪遂,無(wú)論有沒有參數(shù)介蛉,直接調(diào)用Date總是返回當(dāng)前時(shí)間。

構(gòu)造函數(shù)的用法

var d1 = new Date();
//d1 是構(gòu)造函數(shù)Date的實(shí)例

var d2 = new Date();

Date不加參數(shù)溶褪,實(shí)例代表的就是當(dāng)前時(shí)間币旧。

//不寫參數(shù)默認(rèn)是當(dāng)前時(shí)間
var d = new Date();
console.log(d);
//Tue Jul 30 2019 14:22:45 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間)

var d = new Date(2000,10,20,15,30,56);
console.log(d);
//Mon Nov 20 2000 15:30:56 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間)


時(shí)間戳

至?xí)r間零點(diǎn)(1970-1-1 0:0:0)到當(dāng)前時(shí)間所經(jīng)歷的毫秒數(shù)

var d = new Date(0);
console.log(d);
//Thu Jan 01 1970 08:00:00 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間) 
//因?yàn)槲覀兪菛|八區(qū),比如GMT快8小時(shí)

只要是能被Date.parse()方法解析的字符串猿妈,都可以當(dāng)作參數(shù)吹菱。

new Date('2013-2-15')
new Date('2013/2/15')
new Date('02/15/2013')
new Date('2013-FEB-15')
new Date('FEB, 15, 2013')
new Date('FEB 15, 2013')
new Date('Feberuary, 15, 2013')
new Date('Feberuary 15, 2013')
new Date('15 Feb 2013')
new Date('15, Feberuary, 2013')
// Fri Feb 15 2013 00:00:00 GMT+0800 (CST)

getYear 獲取總年數(shù)
var d = new Date();
//1900 ~ 至今經(jīng)歷的總年數(shù)
console.log( d.getYear() );//119

getFullYear 獲取四位年份
var d = new Date();
console.log( d.getFullYear() ); // 2019

getMonth 獲取月份

注意:月份是從0開始計(jì)算,0表示一月

范圍:0 ~ 11

var d = new Date();
console.log( d.getMonth() + 1 ); // 7

getDate 獲取月份

范圍:1 ~ 31

var d = new Date();
console.log( d.getDate()  ); // 30

getDay 獲取星期

注意:0 表示星期日彭则,其余依次類推
范圍:0 ~ 6

var d = new Date();
console.log( d.getDay()  ); // 2

getHours 獲取小時(shí)

范圍:0 ~ 23

var d = new Date();
console.log( d.getHours() );//14

getMinutes 獲取分鐘

范圍:0 ~ 59

var d = new Date();
console.log( d.getMinutes()  ); // 50

getSeconds 獲取秒鐘

范圍:0 ~ 59

var d = new Date();
console.log( d.getSeconds()  ); //29

getMilliseconds 獲取毫秒

范圍:0 ~ 999

var d = new Date();
console.log( d.getMilliseconds()  ); //555

getTime 獲取指定日期的毫秒

var d1 = new Date();
var times = d1.getTime();//獲取1970到當(dāng)前所經(jīng)歷的毫秒數(shù)

//以上代碼也可以改下如下
var times = new Date().getTime();

//獲取指定日期的毫秒數(shù)
var times = new Date('2019-7-31 10:12').getTime();


正則RegExp對(duì)象

正則表達(dá)式表達(dá)文本模式的方法鳍刷,常常用來(lái)按照“給定模式”匹配文本。

什么是正則對(duì)象贰剥?

正則對(duì)象通常使用斜杠包裹起來(lái)的一段字符

正則對(duì)象定義

//構(gòu)造函數(shù)定義
var reg = new RegExp('hello');

//縮寫定義
var reg = /hello/;

什么是正則對(duì)象的修飾符倾剿?

  • i:加i,表示不區(qū)分大小寫
  • g: 加g蚌成,表示全局匹配
  • m:加m前痘,表示多行匹配
//1. 表示不區(qū)分字母a大小寫
var r1 = /a/i; 
var r1 = new RegExp('a','i');

//2. 表示匹配字母a
var r2 = /a/g; 
var r2 = new RegExp('a','g');

//3. 表示全局匹配字母a,字母a不區(qū)分大小担忧。
var r3 = /a/gi; 
var r3 = new RegExp('a','gi');


正則對(duì)象實(shí)例方法

  • test

用于正則模式去匹配給定的文本芹缔,返回布爾值。

語(yǔ)法:

返回布爾類型

正則對(duì)象.test('搜索的文本');

示例

var str = 'hello';
var reg1 = /e/;
var reg2 = new RegExp('e');

console.log( reg1.test( str ) ); //true
console.log( reg2.test( str ) ); //true
console.log( /E/i.test( 'hello' ) );//true
console.log( new RegExp('E','i').test( 'hello' ) );//true

  • exec

正則實(shí)例對(duì)象的exec方法瓶盛,用來(lái)返回匹配結(jié)果最欠。如果發(fā)現(xiàn)匹配,就返回一個(gè)數(shù)組惩猫,成員是匹配成功的子字符串芝硬,否則返回null

當(dāng)有重復(fù)匹配轧房,返回最初匹配的索引值

console.log( /e/.exec('hello') ); 
// ["e", index: 1, input: "hello", groups: undefined]

console.log( /l/.exec('hello') ); 

// ["l", index: 2, input: "hello", groups: undefined]

console.log( /w/.exec('hello') ); 
// null

//組匹配
console.log( /_(x)/.exec('_x_x') );
//["_x", "x", index: 0, input: "_x_x", groups: undefined]

var reg = /a/g;
var result = reg.exec('abc_abc_abc');
console.log( reg.lastIndex );//1

var result = reg.exec('abc_abc_abc');
console.log( reg.lastIndex );//5

var result = reg.exec('abc_abc_abc');
console.log( reg.lastIndex );//9


正則對(duì)象規(guī)則

字面量字符

沒有代表意義的字符拌阴,也就是普通字符,我們叫字面量字符

/dog/.test('old dog') // true
/張三/.test('名稱') // false
/111/.test('名稱') // false

元字符

有代表意義的字符奶镶,特殊字符

  • 點(diǎn)字符(.):表示任意字符迟赃,只匹配一個(gè)字符
console.log( /./.test('dsfdsf232131') ); //true
console.log( /./.test('一二三四') ); //true
console.log( /./.test('1122') ); //true
console.log( /./.test('   ') ); //true
console.log( /./.test('') ); //false

如果要匹配的是點(diǎn)陪拘?

console.log( /\./.test('jpg') );//false

console.log( /\./.test('.jpg') );//true

注意:如果想要元字符表達(dá)字面量字符,可以使用轉(zhuǎn)義符 \

console.log( /:\/\//.test('http://') ); //true

  • 位置字符(^$):
  1. ^ 以什么開頭
  2. $以什么結(jié)尾
console.log( /^\d/.test('2abc') ); //以數(shù)字開頭

console.log( /\d$/.test('abc2') ); //以數(shù)字結(jié)尾

console.log( /^\d$/.test('abc2') ); //以數(shù)字開頭并且以數(shù)字結(jié)尾纤壁,\d只能匹配單個(gè)字符


  • 數(shù)字符 \d: 匹配數(shù)字左刽,只匹配一個(gè)字符
console.log( /\d/.test('d') ); //false

console.log( /\d/.test('3423') ); //true

console.log( /\d/.test('abb1a中') ); //true

console.log( /^\d/.test('1abba中') ); //true

console.log( /^\d$/.test('1abba中1') ); //false
  
console.log( /^\d$/.test('1a') ); //false

console.log( /^\d$/.test('1') ); //true

console.log( /^\d$/.test('123') ); //false,只匹配一個(gè)

  • 數(shù)字符 \D: 匹配非數(shù)字酌媒,只匹配一個(gè)字符
console.log( /^\D$/.test('張') ); //true
console.log( /^\D$/.test('1') ); //false

  • 字母數(shù)字下劃線符 \w:匹配大小字母(a-z A-Z)欠痴、數(shù)字(0-9)、下劃線_
console.log( /^\w$/.test('張') ); //false

console.log( /^\w$/.test('1') ); //true

console.log( /^\w$/.test('a') ); //true

console.log( /^\w$/.test('A') ); //true

console.log( /^\w$/.test('_') ); //true

console.log( /^\w$/.test('-') ); //false

console.log( /^\w$/.test('a1') ); //false

  • 非字母數(shù)字下劃線符 \W: 不匹配非數(shù)字秒咨,只匹配一個(gè)字符
console.log( /^\W$/.test('張') ); //true
console.log( /^\W$/.test('@') ); //true
console.log( /^\W$/.test('%') ); //true

  • 選擇符(|):類似于或的意思
console.log( /^(\d|a)/.test('f') ); //false

console.log( /^(\d|a)/.test('7') ); //true

console.log( /^(\d|a)/.test('7adfg') ); //true

console.log( /^(\d|a)/.test('a1212') ); //true

  • 特殊字符
  1. \n:匹配換行
console.log( /\n/.test(`111 333 222 444`) );//false
console.log( /\n/.test(`111
333`) );//true

  1. \s:匹配空格斋否、換行\n、回車\r拭荤、制表符\t
  console.log( /\s/.test(`111 333 222 444`) );//true
  console.log( /\s/.test(`111
333`) );//true

如果我只想匹配純空格呢茵臭?

console.log( / /.test(`111 333 222 444`) );//true

  1. \S: 匹配非空格、換行\n舅世、回車\r旦委、制表符\t
  2. \uhhhh:匹配一個(gè)以四位十六進(jìn)制數(shù) \u0000-\uFFFF 表示的 Unicode 字符

注意:[\u4e00-\u9fa5]:表示中文字符串集范圍,表示單個(gè)漢字

console.log( /[\u4e00-\u9fa5]/.test(`2`) );//false
console.log( /[\u4e00-\u9fa5]/.test(`a`) );//false
console.log( /[\u4e00-\u9fa5]/.test(`$`) );//false
console.log( /[\u4e00-\u9fa5]/.test(`張`) );//true
console.log( /[\u4e00-\u9fa5]/.test(`張1`) );//true
console.log( /^[\u4e00-\u9fa5]$/.test(`張1`) );//false
console.log( /^[\u4e00-\u9fa5]$/.test(`張`) );//true

  • 白名單符[]:可選范圍
//允許輸入數(shù)字或者下劃線
console.log( /^[0-9_]$/.test(`2`) );//true
console.log( /^[0-9_]$/.test(`a`) );//false
console.log( /^[0-9_]$/.test(`_`) );//true

  • 黑名單符[^]:除可選范圍以為
//不允許輸入數(shù)字或者下劃線
console.log( /^[^0-9_]$/.test(`2`) );//false
console.log( /^[^0-9_]$/.test(`a`) );//true
console.log( /^[^0-9_]$/.test(`_`) );//false

  • 連字符 -:某些情況下雏亚,對(duì)于連續(xù)序列的字符缨硝,連字符(-)用來(lái)提供簡(jiǎn)寫形式
console.log( /^[1-5]$/.test(`2`) );//
console.log( /^[c-f]$/.test(`C`) );//false
console.log( /^[c-f]$/.test(`d`) );//true
console.log( /^[c-f]$/.test(`j`) );//false
console.log( /^[三-五]$/.test(`四`) );//false
console.log( /^[三-五]$/.test(`三`) );//true
console.log( /^[三-五]$/.test(`五`) );//true
  • 分組():將一組字符串分組匹配
console.log(/(abc){2}/.test('abcabc123')); //true
console.log(/(abc){2}/.test('abc123')); //false
  • 匹配邊界\b
var str = 'a|b|c';
var str = '1|2|3|4';

console.log( /^(.+\b\|)+[^\|]$/.test( str ) ); 
  • 匹配非邊界\B

量詞

  • *:代表 0個(gè)、1個(gè)罢低、n個(gè)情況查辩,可有可無(wú)或者很多個(gè)。
console.log( /^\d*$/.test('') );  //true 表示0個(gè)
console.log( /^\d*$/.test('9') ); //true 表示1個(gè)
console.log( /^\d*$/.test('999') ); //true 表示n個(gè)
console.log( /^\d*$/.test(' ') );//false 空格不是數(shù)字
  • +:代表 1個(gè)网持、n個(gè)情況宜岛,至少1個(gè)。
console.log( /^\d+$/.test('') );  //false 至少1個(gè)
console.log( /^\d*$/.test('9') ); //true 表示1個(gè)
console.log( /^\d*$/.test('999') ); //true 表示n個(gè)
console.log( /^\d*$/.test(' ') );//false 空格不是數(shù)字
  • ?:代表 0個(gè)功舀、1個(gè)情況萍倡,要么沒有要么有一個(gè)。
console.log( /^@?$/.test('') );  //true
console.log( /^@?$/.test('@') );  //true
console.log( /^@?$/.test('@@') );  //false
  • {n}:代表允許字符的固定位數(shù)
//必須輸入6位數(shù)字辟汰,這很符合郵政編碼規(guī)則
console.log( /^\d{6}$/.test('12345') );  //false
console.log( /^\d{6}$/.test('123456') );  //true

  • {n,}:代表至少允許n個(gè)字符
console.log( /^\d{6,}$/.test('12345') );//false
console.log( /^\d{6,}$/.test('123456') );//true 
console.log( /^\d{6,}$/.test('123456789') );//true

  • {n,m}:代表至少允許n個(gè)字符列敲,最多m個(gè)字符
console.log( /^\d{6,10}$/.test('12345') );//false
console.log( /^\d{6,10}$/.test('123456') );//true 
console.log( /^\d{6,10}$/.test('123456789') );//true
console.log( /^\d{6,10}$/.test('12345678921311') );//false

貪婪和非貪婪模式

  • 貪婪模式,默認(rèn)貪婪模式
var s = 'aaa';
//貪婪模式
console.log( s.match(/a+/) );//aaa

//非貪婪模式
console.log( s.match(/a+?/) );

//查找 <字母>任意字符</字母>
var str = '<div><h2>標(biāo)題2</h2></div>';

//貪婪模式
console.log( str.match(/^<(.+)>(.*)<\/(.+)>$/) );
// <div><h2>標(biāo)題2</h2></div>

//非貪婪模式
console.log( str.match(/<(\w+)[^>]+>.*?<\/(\w+)>/) );
// <div><h2>標(biāo)題2</h2>

  • 非貪婪模式

如果想將貪婪模式改為非貪婪模式帖汞,可以在量詞符后面加一個(gè)問號(hào)戴而。

var s = 'aaa';
s.match(/a+?/) // ["a"]

m 修飾符

/world$/.test('hello world\n') // false
/world$/m.test('hello world\n') // true

上面的代碼中,字符串結(jié)尾處有一個(gè)換行符翩蘸。如果不加m修飾符所意,匹配不成功,因?yàn)樽址慕Y(jié)尾不是world;加上以后扁眯,$可以匹配行尾。

/^b/.test('a\nb') // false
/^b/m.test('a\nb') // true

字符串對(duì)象實(shí)例使用正則的方法

match

返回一個(gè)數(shù)組翅帜,成員是所有匹配的子字符串

replace

按照給定的正則表達(dá)式進(jìn)行替換姻檀,返回替換后的字符串。

語(yǔ)法:

字符串.replace(/正則對(duì)象/修飾符,用來(lái)替換的字符);

示例

`1aa23A45`.replace(/a/,'*');//1*a23A45
`1aa23A45`.replace(/a/g,'*');//1**23A45
`1aa23A45`.replace(/a/gi,'*');//1**23*45

replace方法的第二個(gè)參數(shù)可以使用美元符號(hào)$涝滴,用來(lái)指代所替換的內(nèi)容绣版。

var str1 = 'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1');
console.log( str1 );// world hello

var str2 = '3 and 5'.replace(/(\d+)\sand\s(\d+)/,'$2 and $1');
console.log( str2 );// 5 and 3

  • $&: 匹配的子字符串
  • $: 匹配結(jié)果前面的文本。
  • $': 匹配結(jié)果后面的文本歼疮。
  • $n:匹配成功的第n組內(nèi)容杂抽,n是從1開始的自然數(shù)朋截。
  • $$:指代美元符號(hào)$
'abc'.replace('b', '[$`-$&-$\']');//a[a-b-c]c

'abc'.replace('b', '[$`-$&-$\']');

注意:用來(lái)替換的字符也可以是一個(gè)函數(shù)

var str = '3 and 5'.replace(/[0-9]+/g, function (match) {
  return 2 * match;
})

console.log( str ); // 6 and 10

經(jīng)典面試題

替換為駝峰法命名

var str1 = 'first-name'; //firstName
var str2 = 'border-top-left-radius';//borderTopLeftRadius
var str3 = 'FiRSt-Name';//firstName

var result = str3.toLowerCase().replace(/-[a-z]/g, function( match ){
  return match.slice(1).toUpperCase();
});

console.log( result );

正則如何使用變量替換
//定義敏感字
var badwords = ['shit','fuck','tmd'];

var str = '今天shit的天tmd氣fuck不錯(cuò)';

//批量替換敏感字
for(var i=0;i<badwords.length;i++){
  var reg = new RegExp( badwords[i] , 'gi' );
  str = str.replace( reg, '*' );
}

document.write( str );

正則替換html標(biāo)簽

清理html標(biāo)簽

//html文本
var str = `<div style="color:red;">
  <span class="red">紅色</span>
  <h1>標(biāo)題1</h1>
  <span>文本</   span>
  <p>段落</p>
</div>`;

//1. 清理html標(biāo)簽
str = str.replace(/<.*?>/g,'');
console.log( str );

2. 清理span標(biāo)簽
str = str.replace(/<\/?(\s*)span(.*?)>/gi,'');
console.log(str);

//3. 清理自定義標(biāo)簽
var lists = ['span','p','h1'];
for( var i=0;i<lists.length;i++){
  var reg = new RegExp('<\/?(\\s*)'+lists[i]+'(.*?)>','gi');
  str = str.replace( reg, '' );
}
console.log( str );

//4. 給字符串對(duì)象擴(kuò)展過濾標(biāo)簽的方法
String.prototype.reTags = function(){
  var str = this;
  var args = arguments;
  for(var key in args){
    var reg = new RegExp(`<\/?(\\s*)${args[key]}(.*?)>`,'gi');
    str = str.replace( reg,'');
  }
  return str;
}

var result = str.reTags('span','p','h1');
console.log( result );

先行斷言

x(?=y)稱為先行斷言柜与,x只有在y前面才匹配渔欢,y不會(huì)被計(jì)入返回結(jié)果锐朴。

示例

//60只有在%前面才匹配声功,%不會(huì)被計(jì)入返回結(jié)果娶聘。
console.log( '60%'.match(/\d+(?=%)/) );//60
console.log( '%60'.match(/\d+(?=%)/) );//null
console.log( '60'.match(/\d+(?=%)/) );//null

先行否定斷言
//先行斷言

//60只有在%前面才匹配术唬,%不會(huì)被計(jì)入返回結(jié)果域醇。
console.log( '60%'.match(/\d+(?=%)/) );//60
console.log( '%60'.match(/\d+(?=%)/) );//null
console.log( '60'.match(/\d+(?=%)/) );//null

console.log( '80%12%34903%33'.match(/\d+(?=%)/g) );
// ['80','12','34903']

console.log('a.jpg,b.gif,c.png'.match(/\w+(?=,)|\w+(?=$)/g));
//['a.jpg','b.gif','c.png']

var str = 'a.jpg,b.gif,c.png';
console.log( str.match(/(\w+)(?=(,|$))/g) );
//['a.jpg','b.gif','c.png']

先行否定斷言

x(?!y)x只有不在y前面才匹配吹散,y不會(huì)被計(jì)入返回結(jié)果弧械。

//先行否定斷言

//60只有不在%前面才匹配,%不會(huì)被計(jì)入返回結(jié)果空民。
console.log( '60%'.match(/\d+(?!%)/) );//6
console.log( '%60'.match(/\d+(?!%)/) );//60

JSON對(duì)象

JSON對(duì)象本質(zhì)其實(shí)就是一段字符串刃唐,只是這個(gè)字符串它有一定規(guī)則。

目的是取代繁瑣笨重的 XML 格式

json文本鍵名是用雙引號(hào)界轩,鍵值如果是字符串画饥,需要雙引號(hào),數(shù)字可以不需要

數(shù)組或?qū)ο笞詈笠粋€(gè)成員的后面浊猾,不能加逗號(hào)荒澡。

什么xml文本?

<?xml version="1.0" encoding="utf-8"?>
<students>
    <student>
        <sn>201709000123</sn>
        <name>張嘉佳</name>
        <sex>女</sex> 
        <nation>漢族</nation>
        <address>湖北武漢</address>
        <profession>英語(yǔ)</profession>
    </student>
    <student>
        <sn>201709000124</sn>
        <name>李文斌</name>
        <sex>男</sex> 
        <nation>傣族</nation>
        <address>云南昆明</address>
        <profession>建筑</profession>
    </student>
</students>

什么json文本与殃?

[
  {
    "sn": "201709000123",
    "name": "張嘉佳",
    "sex": "女",
    "nation":"漢族",
    "address":"湖北武漢",
    "profession":"語(yǔ)言"
  },
  {
    "sn": "201709000123",
    "name": "張嘉佳",
    "sex": "女",
    "nation":"漢族",
    "address":"湖北武漢",
    "profession":"語(yǔ)言"
  }
]

jsonxml比較:

  • 可讀性:xml
  • 生成數(shù)據(jù)方面:json
  • 傳輸速度方面:json
  • xml誕生很早单山,可以支持一些很老的設(shè)備

json文本中復(fù)合類型中不能有函數(shù)

以下寫法錯(cuò)誤

{
  "getname": function(){

  }
}

以下寫法正確

{
  "name": "張三",
  "info": [
    {
      "id": 1,
      "title": "標(biāo)題1",
      "check": "true"
    }
  ]
}

以下都是合法的 JSON。

["one", "two", "three"]

{ "one": 1, "two": 2, "three": 3 }

{"names": ["張三", "李四"] }

[ { "name": "張三"}, {"name": "李四"} ]

以下都是不合法的 JSON幅疼。

{ name: "張三", 'age': 32 }  // 屬性名必須使用雙引號(hào)

[32, 64, 128, 0xFFF] // 不能使用十六進(jìn)制值

{ "name": "張三", "age": undefined } // 不能使用 undefined

{ "name": "張三",
  "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
  "getName": function () {
      return this.name;
  }
} // 屬性值不能使用函數(shù)和日期對(duì)象

注意米奸,null、空數(shù)組和空對(duì)象都是合法的 JSON 值爽篷。

JSON對(duì)象全局方法
  • JSON.stringify()

返回經(jīng)過轉(zhuǎn)換過后的字符串

語(yǔ)法:

JSON.stringify(需要轉(zhuǎn)換的對(duì)象或數(shù)組,用于過濾指定屬性,可讀性);

示例

JSON.stringify('abc') // ""abc""
JSON.stringify(1) // "1"
JSON.stringify(false) // "false"
JSON.stringify([]) // "[]"
JSON.stringify({}) // "{}"

JSON.stringify([1, "false", false])
// '[1,"false",false]'

JSON.stringify({ name: "張三" })
// '{"name":"張三"}'

第二參數(shù)示例: 過濾指定的屬性

var obj = {
  'name': '張三',
  'age': '20',
  'sex': '男'
};
var selectedProperties = ['name', 'sex'];
var str = JSON.stringify(obj, selectedProperties);
console.log( str );//{"name":"張三","sex":"男"}

第三參數(shù)示例:

var obj = {
  'name': '張三',
  'age': '20',
  'sex': '男',
  info: {
    'a': 20
  }
};
var str = JSON.stringify(obj, null, 2);
//可讀性就比較好
// {
//   "name": "張三",
//   "age": "20",
//   "sex": "男",
//   "info": {
//     "a": 20
//   }
// }

JSON.parse()

JSON.parse方法用于將 JSON 字符串轉(zhuǎn)換成對(duì)應(yīng)的值悴晰。

JSON.parse('{}') // {}
JSON.parse('true') // true
JSON.parse('"foo"') // "foo"
JSON.parse('[1, 5, "false"]') // [1, 5, "false"]
JSON.parse('null') // null

var o = JSON.parse('{"name": "張三"}');
o.name // 張三

DOM模型

DOM:文檔對(duì)象模型( Document Object Model ),它的作用是將網(wǎng)頁(yè)轉(zhuǎn)為一個(gè) js 對(duì)象

節(jié)點(diǎn) Node

DOM最小組成單位叫做節(jié)點(diǎn)

節(jié)點(diǎn)的類型有七種:

  • Document:整個(gè)文檔節(jié)點(diǎn)(包含整個(gè)節(jié)點(diǎn)樹)
  • DocumentType:文檔聲明類型 <!DOCTYPE html>
  • Element:元素節(jié)點(diǎn),網(wǎng)頁(yè)的各種HTML標(biāo)簽(<body>铡溪、div漂辐、img等等)
  • Attribute:網(wǎng)頁(yè)元素的屬性(比如class="right"
  • Text:標(biāo)簽之間或標(biāo)簽包含的文本
  • Comment:注釋
  • DocumentFragment:文檔的片段

根節(jié)點(diǎn)

document 根節(jié)點(diǎn),文檔的第一層只有一個(gè)節(jié)點(diǎn)

節(jié)點(diǎn)的關(guān)系

除了根節(jié)點(diǎn)棕硫,其他節(jié)點(diǎn)都有三種層級(jí)關(guān)系髓涯。

  • 父節(jié)點(diǎn)關(guān)系
<!-- button的直接父節(jié)點(diǎn)是div -->
<div>
  <button>按鈕</button>
</div>

  • 子節(jié)點(diǎn)關(guān)系
<!-- div的直接子節(jié)點(diǎn)是button -->
<div>
  <button>按鈕</button>
</div>

  • 同級(jí)節(jié)點(diǎn)關(guān)系
<!-- button的同級(jí)節(jié)點(diǎn)是h2 -->
<div>
  <button>按鈕</button>
  <h2>標(biāo)題2</h2>
</div>

Node 接口的屬性

所有 DOM 節(jié)點(diǎn)都繼承了 Node 接口

  • Node.nodeType:

返回一個(gè)整數(shù)值,表示節(jié)點(diǎn)的類型哈扮,有以下類型:

  1. document:9 表示 文檔
  2. element: 1 表示 元素
  3. attr: 2 表示 屬性
  4. text: 3 表示 文本
  5. DocumentFragment: 11 表示 文檔片段
  6. DocumentType: 10 表示 文檔類型
  7. Comment: 8 表示 注釋
<div id="box">你好</div>
<script>
  var box = document.getElementById('box');
  console.log( box.nodeType ); //1 元素
  console.log( box.childNodes[0].nodeType );//3 文本
</script>

  • Node.nodeName:
<div id="box">你好</div>
<script>
  var box = document.getElementById('box');
  console.log( box.nodeName ); //DIV 默認(rèn)是大寫
  console.log( box.childNodes[0].nodeName );//#text
</script>

  • Node.nodeValue

nodeValue屬性返回一個(gè)字符串纬纪,表示當(dāng)前節(jié)點(diǎn)本身的文本值

注意:該屬性主要用于文本節(jié)點(diǎn)

var box = document.getElementById('box');
console.log( box.nodeValue );//null
console.log( box.childNodes[0].nodeValue );//您好

  • Node.textContent:

textContent屬性返回當(dāng)前節(jié)點(diǎn)和它的所有后代節(jié)點(diǎn)的文本內(nèi)容。

自動(dòng)忽略當(dāng)前節(jié)點(diǎn)內(nèi)部的HTML標(biāo)簽滑肉,提取文本內(nèi)容包各,它和innerText功能一樣

該屬性可讀可寫

<div id="box">
  您好
  <p>
    張三
  </p>
</div>

<script>
  var box = document.getElementById('box');
  console.log( box.textContent );// 您好 張三
</script>
  • Node.baseURI

返回一個(gè)字符串,表示當(dāng)前網(wǎng)頁(yè)的絕對(duì)路徑

會(huì)受<base href="#"> 基礎(chǔ)地址影響靶庙,而location.href不會(huì)问畅。

console.log( document.baseURI );
//file:///F:/studyspace/web1905/javascript/dom.html

console.log( window.location.href );
//file:///F:/studyspace/web1905/javascript/dom.html
  • Node.ownerDocument

返回當(dāng)前節(jié)點(diǎn)所在的頂層文檔對(duì)象,即document對(duì)象六荒。

<div id="box">

</div>

<script>
  var box = document.getElementById('box');
  console.log( box.ownerDocument == document );//true
</script>

節(jié)點(diǎn)關(guān)系查找

父節(jié)點(diǎn)關(guān)系
  • Node.childNodes:

    父節(jié)點(diǎn)下所有的子節(jié)點(diǎn)按声,注意包含文本、注釋恬吕、元素節(jié)點(diǎn)

  • Node.children:

    父節(jié)點(diǎn)下所有的子元素節(jié)點(diǎn)签则,只是元素節(jié)點(diǎn)

  <ul id="box">
  <li>一分</li>
  <li>二分</li>
  <li>三分</li>
  <li>四分</li>
  <li>五分</li>
</ul>

<script>
var box = document.getElementById('box');
var lis1 = box.childNodes;
var lis2 = box.children;

console.log( lis1, lis2);
</script>
子節(jié)點(diǎn)關(guān)系
  • parentNode

    當(dāng)前節(jié)點(diǎn)的直接的父節(jié)點(diǎn)

  • parentElement

    當(dāng)前節(jié)點(diǎn)的直接的父元素節(jié)點(diǎn)

<div>
  <span>
    <button id="btn">按鈕</button>
  </span>
</div>

<script>
document.getElementById('btn').onclick = function(){
  var THIS = this;
  while( THIS.parentElement ){
    THIS = THIS.parentElement;
    if(THIS.nodeName == 'BODY'){
      THIS.style.backgroundColor='red';
    }
  }
}
</script>

同級(jí)節(jié)點(diǎn)關(guān)系

  • Node.nextSibling

    下一個(gè)節(jié)點(diǎn),注意包含文本铐料、注釋渐裂、元素節(jié)點(diǎn)

  • Node.nextElementSibling:

    下一個(gè)元素節(jié)點(diǎn),只是元素節(jié)點(diǎn)钠惩。

<button onclick="setBox(this)">按鈕</button>
<div></div>

<script>
//單擊按鈕柒凉,給div設(shè)置寬200 高200 背景顏色紅色
function setBox( btn ){
  btn.nextElementSibling.style.cssText = `width:200px;height:200px;background-color:red`;
}
</script>
  • Node.previousSibling

    上一個(gè)節(jié)點(diǎn),注意包含文本篓跛、注釋膝捞、元素節(jié)點(diǎn)

  • Node.previousElementSibling

    上一個(gè)元素節(jié)點(diǎn),只是元素節(jié)點(diǎn)愧沟。

    綜合的例子

    <ul>
    <li>一分</li>
    <li>二分</li>
    <li>三分</li>
    <li>四分</li>
    <li>五分</li>
    </ul>
    
var lis = document.querySelectorAll('li');

lis.forEach( function( item ){

  item.onclick = function(){
    var THIS1 = this;
    var THIS2 = this;
//查找當(dāng)前元素往上的所有元素
while( THIS1.previousElementSibling ){
  THIS1 = THIS1.previousElementSibling;
  THIS1.className = 'active' 
}

//查找當(dāng)前元素往下的所有元素
while( THIS2.nextElementSibling ){
  THIS2 = THIS2.nextElementSibling;
  THIS2.className = 'active' 
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蔬咬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子沐寺,更是在濱河造成了極大的恐慌林艘,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件混坞,死亡現(xiàn)場(chǎng)離奇詭異狐援,居然都是意外死亡钢坦,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門啥酱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)爹凹,“玉大人,你說(shuō)我怎么就攤上這事镶殷『探矗” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵批钠,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我得封,道長(zhǎng)埋心,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任忙上,我火速辦了婚禮拷呆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘疫粥。我一直安慰自己茬斧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布梗逮。 她就那樣靜靜地躺著项秉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪慷彤。 梳的紋絲不亂的頭發(fā)上娄蔼,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音底哗,去河邊找鬼岁诉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛跋选,可吹牛的內(nèi)容都是我干的涕癣。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼前标,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼坠韩!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起炼列,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤同眯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后唯鸭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體须蜗,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了明肮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片菱农。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖柿估,靈堂內(nèi)的尸體忽然破棺而出循未,到底是詐尸還是另有隱情,我是刑警寧澤秫舌,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布的妖,位于F島的核電站,受9級(jí)特大地震影響足陨,放射性物質(zhì)發(fā)生泄漏嫂粟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一墨缘、第九天 我趴在偏房一處隱蔽的房頂上張望星虹。 院中可真熱鬧,春花似錦镊讼、人聲如沸宽涌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)卸亮。三九已至,卻和暖如春玩裙,著一層夾襖步出監(jiān)牢的瞬間嫡良,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工献酗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留寝受,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓罕偎,卻偏偏與公主長(zhǎng)得像很澄,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子颜及,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容