變數作用域:
1、全域變數:在全域作用域下宣告的變數
? 在函式內部沒有宣告直接賦值的變數也是屬于全域變數
全域變數:只有瀏覽器關閉的時候才會銷毀,比較占記憶體資源
區域變數 :當我們程式執行完畢就會銷毀,比較節約記憶體資源
作用域鏈:內部函式訪問外部函式的變數,采取的是鏈式查找的方式來決定取哪個值 這種結構我們稱之為作用域鏈 就近原則
var申明變數會存在變數提升
js引擎運行js分為兩步:
1、決議 2、代碼執行
? (1)預決議:js 引擎會把 js 里面所有的 var 和 function 提升到當前作用域的最前面,
? (2)代碼執行:按照代碼速寫的順序從上往下執行
2、預決議分為變數預決議(變數提升)和函式預決議(函式提升)
? (1)變數提升:就是把所有的變數宣告提升到當前的作用域最前面 不提升賦值操作
? (2)函式提升:就是把所有的函式宣告提升到當前作用域的最前面 不呼叫函式
建構式:
? 1.建構式名字首字母要大寫
? 2.建構式不需要return 就可以回傳結果
? 3.呼叫建構式必須使用new
? 4.只要new Star() 呼叫函式就創建了一個物件
object.setAttribute(sName, vValue [, iFlags]):給元素設定自定義屬性
引數:
sName
必填項. String型別,屬性名
vValue
必填項. 為屬性指定的變數,可以為string, number, 或者 Boolean型別
iFlags
選填. 下面指定的兩種 Integer 型別的標志
0
覆寫同名屬性.
1
默認值. 為屬性添加指定的值.
let attribute = element.getAttribute(attributeName);查看元素的自定義屬性
attribute是一個包含attributeName屬性值的字串,attributeName是你想要獲取的屬性值的屬性名稱,- 回傳屬性的值
添加事件監聽:addEventlistener(事件,函式)
事件捕獲和事件冒泡
事件捕獲:發生事件時從document一級一級往下尋找目標
事件冒泡:當一個元素的事件被觸發時,同樣的事件將會在該元素的所有祖先元素中依次被觸發,這一程序被稱之為事件冒泡(簡單理解:當一個元素觸發事件后,會依次向上呼叫所有父級元素的同名事件)
阻止事件冒泡:
- 因為默認就有冒泡模式的存在,所以容易導致事件影響到父級元素
- 若想把事件就限制在當前元素內,就需要阻止事件流動
- 阻止事件流動需要拿到事件物件
- 語法:
事件物件.stopPropagation()
- 此方法可以阻斷事件流動傳播,不光在冒泡階段有效,捕獲階段也有效
事件委托
-
事件委托是利用事件流的特征解決一些開發需求的知識技巧
-
優點:給父級元素添加事件(可以提高性能)
-
原理:事件委托其實是利用事件冒泡的特點,給父元素添加事件,子元素可以觸發
-
實作:
事件物件.target可以獲得真正觸發事件的元素// 具體案例代碼見:/Users/shenguangmin/資料/代碼檔案/javascript/28.事件委托.html // 不要給每個小li注冊事件了, 而是把事件委托給他的爸爸 // 事件委托是給父級添加事件, 而不是給兒子添加事件 let ul = document.querySelector('ul') ul.addEventListener('click',function(e){ // console.log(e); // // 得到當前點擊的具體元素 // console.log(e.target); //對應的li標簽變成紅色 e.target.style.color = 'red'; })
事件物件的常用物件方法:
阻止冒泡傳播:stopPropagation()
獲取當前的被操作的物件:target()
阻止默認事件的發生:preventDefult()
等待頁面內容全部記載完畢:load()
等待DOM加載完畢,不包含圖、css等等:DOMContentLoaded()
定時器(只呼叫一次):setTimeout(函式,延時時間)
var t1 = setTimeout(function () {
console.log('時間到')
}, 3000)
清除定時器:clearTimeout(定時器名稱)/clearInterval(定時器名稱)
var t1 = setTimeout(function () {
console.log('時間到')
}, 3000)
var btn = document.querySelector('button')
btn.addEventListener('click', function () {
clearTimeout(t1)
console.log('已阻止');
})
間歇函式 setInterval(函式,間隔時間)
每隔一段時間執行setInterval中的函式
let s1 = setInterval(function () {
console.log('持續輸出')
}, 1000)
關閉定時器 clearInterval(變數名)
let 變數名 = setInterval(函式,間隔時間)
clearInterval(變數名)
offset和style的區別
offset可以得到任意樣式表中的樣式值
? 所以我們想要獲取元素大小位置,用offset更合適
style只能得到行內樣式表中的樣式值
? 所以我們想要給元素更改值,則需要用style改變
立即執行函式
作用:創建一個獨立的作用域,避免了命名沖突問題
兩種寫法:(function(){})() 或者 (function(){}())
獲取dom元素
let box = document.querySelector('div') //回傳一個dom物件
修改dom的樣式 (className屬性)
dom.className = 'newClassName'
格式化輸出
let i = 'tuoni'
console.log(`名字叫${i}`) //用反引號包裹
事件監聽 addEventListener('事件',觸發事件后執行的函式)
let btn = document.querySelector('button')
btn.addEventListener('click',function () {
console.log('被點擊了!')
)
回呼函式
如果將函式A作為引數傳遞給函式B時,我們稱函式A為回呼函式
簡單理解:當一個函式被當做引數來傳遞給另外一個函式的時候,這個函式就是回呼函式
常見的使用場景:
function fn(){
console.log('我是回呼函式...')
}
// fn傳遞給了setInterval,fn就是回呼函式
setInterval(fn, 1000)
事件物件
1.什么是事件物件?
? 也是個物件,這個物件是有事件觸發時的相關資訊
2.事件物件在哪里?
? 在事件系結的回呼函式的第一個引數就是事件物件
元素.addEventListener('click', function(e){}) // 這里的e就是滑鼠的事件物件
常用的事件物件中的屬性:
type:獲取當前的事件型別
clientX/clientY:獲取游標相當于瀏覽器可見視窗左上角的位置
offsetX/offsetY:獲取游標相當于當前DOM元素左上角的位置
key:用戶按下的鍵盤鍵的值,現在不提倡使用keyCode
srcroll家族
scrollWidth和scrollHeight:獲取元素的內容總寬高(不含滾動條)回傳值不帶單位
scrollLeft和 scrollTop:獲取元素內容往左、往上滾出去看不到的距離
:屬性可以修改
offset家族
offsetWidth和offsetHeight:獲取元素的自身寬高、包含元素自身設定的寬高、padding、border
offsetLeft和offsetTop:獲取元素距離自己定位父級元素的左、上距離
注意:offsetLeft和offsetTop是只讀屬性不能修改
client家族
clientWidth和clientHeight:獲取元素的可見部分寬高(不含滾動條和邊框)
clientLeft和clientTop:獲取元素的位置
js中的同步異步執行順序(即事件回圈)
1.先執行執行堆疊中的同步任務
2.異步任務放入任務隊中
3.一旦執行堆疊中的所有同步任務執行完畢,系統就會按次序讀取任務佇列中的異步任務,于是被讀取的異步任務結束等待狀態,進入執行堆疊,開始執行
注意:如果存在多個異步任務,會根據異步任務的實際情況來決定他們的優先級
location物件
location的資料型別是物件,它拆分并保存了URL地址的各個組成部分
常用屬性和方法:
? href屬性獲取完整的URL地址,對其賦值時用于地址跳轉
? search屬性獲取地址中攜帶的引數,符號?后面部分
? hash屬性獲取地址中的哈希值,符號#后面部分
? reload方法用來重繪當前頁面,傳入引數true時表示強制重繪
本地存盤 localStorage
- 存盤簡單資料型別
存盤資料:localStorage.setItem('key', value)
讀取資料:localStorage.getItem('key')
洗掉資料:localStorage.removeItem('key')
-
存盤復雜資料型別
本地只能存盤字串,無法存盤復雜資料型別,需要將復雜資料型別轉換成JSON字串,再存盤到本地
JSON.stringify(復雜資料型別)
JSON.stringify(復雜資料型別)
將復雜資料型別轉換成JSON字串 存盤到本地存盤中
JSON.parse(JSON字串)
將JSON字串轉換成物件 取出時候使用
正則
定義:用let re = /正則運算式/的方式定義正則運算式,得到一個正則物件
test(): 用于判斷是否有符合規則的字串,回傳的是布林值
let re = /.*/
console.log(re.test('slasjdf')); // true
exec(): 用于查找符合規則的字串,回傳一個陣列
let re = /.*/
console.log(re.exec('slasjdf')); // ['slasjdf']
面向物件(類,es6新增)
創建類的關鍵字:class
類中的構造方法:constructor()
實體化物件的關鍵字:new
class Student{
constructor(name, age){
this.name = name
this.age = age
}
}
let user = new Student('tuoni', 18)
類的繼承
繼承的關鍵字:extends
class Father{
constructor(x, y){
this.x = x;
this.y = y;
}
sum(){
console.log(this.x + this.y);
}
say(){
console.log('我是爸爸')
}
}
class Son extends Father{
constructor(x, y){
super(x, y); //呼叫了父類中的建構式,必須放在子類中this之前
// super.say() // 呼叫了父類中的其他方法
}
}
var son = new Son(1, 2);
son.sum();
插入新的標簽
element.insertAdjacentHTML(position, text)
-
position一個
DOMString,表示插入內容相對于元素的位置,并且必須是以下字串之一:'beforebegin':元素自身的前面,'afterbegin':插入元素內部的第一個子節點之前,'beforeend':插入元素內部的最后一個子節點之后,'afterend':元素自身的后面, -
text是要被決議為 HTML 或 XML 元素,并插入到 DOM 樹中的
DOMString,
建構式創建物件(es6之前)
- 建構式
建構式是一種特殊的函式,主要用來初始化物件即為物件成員變數賦初始值,它總與new一起使用,我們可以把物件中一些公共的屬性和方法抽取出來,然后封裝到這個函式里面,
-
new在執行時會做四件事情
-
在記憶體中創建一個新的空物件
-
讓this指向這個新的物件
-
執行建構式里面的代碼,給這個新物件添加屬性和方法
-
放回這個新物件(所以建構式里面不需要 return)
-
function Student(name, age) {
this.name = name;
this.age = age;
this.run = function(){
console.log('跑');
}
}
var student1 = new Student('tuoni', 19);
var student2 = new Student('張學友', 29);
console.log(student1.age);
console.log(student2.age);
console.log(student1.run());
console.log(student2.run());
-
實體成員與靜態成員
- 實體成員就是建構式內部通過this添加的成員 name age run就是實體成員,實體成員只能通過實體化的物件來訪問
- 靜態成員 在建構式本身上添加的成員 sex 就是靜態成員,靜態成員只能通過建構式來訪問
function Student(name, age) { this.name = name; this.age = age; this.run = function(){ console.log('跑'); } } var student1 = new Student('tuoni', 19); Student.sex = '男'; // 靜態成員 console.log(Student.sex); // 只能通過建構式訪問缺點:使用建構式創建物件會浪費很多的記憶體空間,使用
new實體化物件時會開辟一個記憶體空間將基本資料型別存盤在這個記憶體空間中,然后會開辟另一個新的記憶體空間用來保存復雜資料型別(如:方法),那么多個物件訪問的同名方法并不是在同一記憶體空間中,而是各自的記憶體空間,解決:使用原型物件保存公共方法
建構式原型 prototype
建構式通過原型分配的函式是所有物件所共享的
JavaScript規定,每一個建構式都有一個prototype屬性,指向的是另一個物件,注意這個prototype就是一個物件,這個物件的所有屬性和方法,都會被建構式所擁有
我們可以把那些不變的方法,直接定義在prototype物件上,這樣所有物件的實體就可以共享這些方法,
function Student(name, age) {
this.name = name;
this.age = age;
Student.prototype.run = function () {
console.log('跑');
}
}
var student1 = new Student('tuoni', 19);
var student2 = new Student('孫悟空', 29);
student1.run(); // 跑
student2.run(); // 跑
console.log(student1.run === student2.run); // true 說明記憶體地址相同
物件原型
為什么studnet1物件可以直接呼叫prototype物件中的run方法?
? 因為每個物件身上會有一個__proto__屬性,這個屬性等價于建構式中prototype屬性
方法的查找規則:首先看student1物件身上是否有run方法,如果有就執行這個物件上的run方法,如果沒有,因為有__proto__的存在,就去建構式原型物件prototype身上去查找
-
constructor是原型物件prototype中的一個屬性,記錄著物件的建構式(由哪個建構式所創建)如果我們修改了原來的原型物件,給原型物件賦值的是一個物件,則必須手動的利用
constructor指回原來的建構式如下:function Student(name, age) { this.name = name; this.age = age; Student.prototype = { constructor: Student, run: function () { console.log('跑'); }, sing: function () { console.log('唱歌'); } } } var student1 = new Student('tuoni', 19); console.log(student1.__proto__.constructor); // 建構式Student原型鏈
每個實體物件都會自帶一個__proto__屬性(原型),在上圖中Star原型物件中也出現了__proto__屬性(原型),說明Star的原型物件也是一個物件,那么Star原型物件__proto__屬性(原型)來自于Object原型物件中,最終Object原型物件中的__proto__指向null
JavaScript的成員查找機制(規則)
- 當訪問一個物件的屬性(包括方法)時,首先查找這個物件自身有沒有該屬性
- 如果沒有就查找它的原型(也就是
__proto__指向的prototype原型物件) - 如果還沒有就查找原型物件的原型(Object的原型物件)
- 以此類推一直找到Object為止(null)
__proto__物件原型的意義就在于為物件成員查找機制提供一個方向,或者說一條線路
call方法改變this指向
fn.call(obj,形參1,形參2)
fn : 需要執行的函式
obj : 需要指向的物件
形參 :被執行函式所需要的引數
類的本質
class本質還是function- 類的所有方法都定義在類的
prototype屬性上 - 類創建的實體,里面也有
__proto__指向類的prototype原型物件 - 所以ES6的類他的絕大部分功能,ES5都可以做到,新的
class寫法只是讓物件原型的寫法更加清晰、更像面向物件編程的語法而已 - 所以ES6的類其實就是語法糖
ES5中的新增方法
陣列方法
forEach 迭代(遍歷)陣列
array.forrEach(function(currentValue, index, arr))
currentValue: 陣列當前項的值index:陣列當前項的索引arr:陣列物件本身
var list = [1, 2, 3, 34, 5]
list.forEach(function (value, index, arr) {
console.log(value);
console.log(index);
console.log(arr);
})
filter()
filter()方法創建一個新的陣列,新陣列中的元素是通過檢查指定陣列中符合條件的所有元素,主要用于篩選陣列
array.filter(function(currentValue, index, arr))
- 注意它直接回傳一個新的陣列
currentValue: 陣列當前項的值index: 陣列當前項的索引arr: 陣列物件本身
var li = [1, 2, 3, 4, 5]
var ar = li.filter(function (value, index, arr) {
return value > 3;
})
console.log(ar); // [4, 5]
some()
some()方法用于檢測陣列中的元素時候滿足指定條件,通俗點說查找陣列中是否有滿足條件的元素- 注意它回傳值是布林值,如果查找到這個元素,就回傳true,如果查找不到就回傳false
- 如果找到第一個滿足條件的元素,則終止回圈,不在繼續查找
currentValue: 陣列當前項的值index: 陣列當前項的索引arr: 陣列物件本身
var li = [1, 2, 3, 4, 5]
var ar = li.some(function (value, index, arr) {
return value > 3;
})
console.log(ar); // true
物件方法
Object.defineProperty()定義新屬性或修改原有的屬性
Object.defineProperty(obj, prop, descriptor)
obj : 被操作的物件
prop : 屬性名
descriptor : 說明,以物件形式{ }書寫
- value : 設定屬性的值 默認為undefined
- writable :值是否可以重寫, true|false 默認為false
- enumerable :目標屬性是否可以被列舉,true|false 默認為false
- configurable:目標屬性是否可以被洗掉或是否可以再次修改特性true|false默認為false
var obj = {
name: '1231',
age: '232222'
}
Object.defineProperty(obj, 'sex', {
value: '男',
// 如果為false 不允許修改這個屬性值
writable:false,
// 如果為false 不允許遍歷
enumerable:false,
// 如果為false 不允許洗掉這個屬性 不允許在修改第三個引數里的特性
configurable:false
})
字串方法
trim()方法會從一個字串的兩端洗掉空白字符,并回傳一個新的字串
let st = ' andy '
console.log(st.trim()) // 'andy'
Object.keys(obj)
獲取物件中所有的鍵,以串列的形式回傳
var obj = {
name: '1231',
age: '232222'
}
console.log(Object.keys(obj)); //['name', 'age']
bind方法
bind()方法不會呼叫函式,但是能改變函式內部this指向
fun.bind(thisArg, arg1, arg2, ...)
thisArg: 在fun函式運行時指定的this值arg1,arg2: 傳遞的其他引數- 回傳由指定的this值和初始化引數改造的原函式拷貝
var obj = {
name: 'tuoni',
age: '19'
}
function fn(){
console.log(this);
}
var f = fn.bind(obj)
f() // 指向obj
ES6語法
let 關鍵字
- 不能重復宣告:
let a = 1;
let a = 2; // 報錯
-
與var不同,沒有變數提升
-
擁有塊級作用域(在大括號中的才會存在)
if (true){
let a = 1
}
console.log(a) //報錯
-----------------------------
{
let name = 'tuoni'
}
console.log(name) // 報錯
const 關鍵字
-
不能重復宣告:
const a = 1; const a = 2; // 報錯 -
用來定義常量,定義后不能修改,但是可以修改復雜資料型別
const a = 1; a = 2 ; console.log(a); // 報錯 const list = [1,2,3]; list.push(4); console.log(list); // [1,2,3,4]
箭頭函式
- 無法改變箭頭函式中的this指向,this始終指向函式宣告時所在作用域下的this的值
// 普通函式
function a() {
console.log(this);
}
// 箭頭函式
let b = () => {
console.log(this)
}
a() // window
b() // window
let obj = {
name: 'tuoni'
}
a.call(obj) // tuoni
b.call(obj) // window
-
不能作為建構式實體化物件
let Person = (name, age) => { this.name = name; this.age = age; } let me = new Person('tuoni', 19) console.log(me); // 報錯
物件定義簡寫
let obj = {
name,
say(){
console.log('hhhhhh')
}
}
等同于>>>>>>
let obj = {
name: ''
say: function(){
console.log('hhhhhh')
}
}
迭代器(需要自定義遍歷資料的時候)
迭代器(iterator)是一種介面,為各種不同的資料結構提供統一的訪問機制,任何資料結構只要部署 iterator 介面(物件中的一個屬性),就可以完成遍歷操作,
- ES6創造了一種新的遍歷命令for...of回圈,
iterator介面主要提供for...of 消費 - 原生具備
iterator介面的資料(可用for of遍歷)- Array
- Arguments
- Set
- Map
- String
- TypeArray
- NodeList
- 作業原理
- 創建一個指標物件,指向當前資料結構的起始位置
- 第一次呼叫物件的next方法,指標自動指向資料結構的第一個成員
- 接下來不斷呼叫next方法,指標一直往后移動,直到指向最后一個成員
- 每呼叫next方法回傳一個包含value和done屬性的物件
給自定物件添加iterator介面實作for...of遍歷:
let obj = {
name: '終極一班',
stus: [
'xiaomin',
'xiaohuam',
'xiaogao',
'tuoni'
],
[Symbol.iterator]() {
// 索引變數
let index = 0;
let _this = this
return {
next: function () {
if (index < _this.stus.length) {
const result = { value: _this.stus[index], done: false }
index++;
return result
} else {
return { value: undefined, done: true }
}
}
}
}
}
// 使用for of 對物件進行自定義遍歷
for (const i of obj) {
console.log(i);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/541523.html
標籤:其他
上一篇:【前端除錯】- 借助Performance分析并優化性能
下一篇:CSS優先級-權重疊加計算
