函數的復習:
- 自定義函數和調用函數
<script>
// 自定義函數
fun(); // 調用函數 放到哪個位置都可以
function fun() {
console.log(3);
}
var fn = function() {
console.log(4);
}
fn(); // 調用函數 必須再函數聲明的下面 先聲明后使用
</script>
- 全局變量和局部變量
<script>
// 變量的作用域 全局變量 和 局部變量
var key = "你好嗎"; // 全局變量
function fun() {
var num = 10; // 再函數內部聲明的 內部變量
console.log(num);
console.log(key);
}
fun();
console.log(num);
</script>
閉包
在程序語言中,所謂閉包醉鳖,是指語法域位于某個特定的區(qū)域,具有持續(xù)參照(讀寫)位于該區(qū)域內自身范圍之外的執(zhí)行域上的非持久型變量值能力的段落哮内。這些外部執(zhí)行域的非持久型變量神奇地保留他們在閉包最初定義(或創(chuàng)建)時的值盗棵。
白話: 我們可以用一個函數 去訪問 另外一個函數的內部變量的方式就是閉包。
內部變量 是 局部變量 那我們知道,局部變量是不可以為別人隨便使用也纹因。
閉包常用寫法★★★★★
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
</body>
</html>
<script>
function outFun() {
var num = 10;
function inFun() {
console.log(num); // 非常正常的寫法
}
return inFun; // !!核心E缥荨! 這里無括號即 返回的是 inFun函數體 瞭恰;若加括號返回的是結果
}
// 使用
console.log(outFun());
var demo = outFun(); // 看清楚 此處加了小括號
// outFun() 返回的是 function inFun() {console.log(num); }
// 相當于 這句話 var demo = function inFun() {console.log(num); }
demo();
</script>
其實每個函數都算一個小閉包:
加強閉包的認識(面試題):
<script>
function outerFun() // 外部函數
{
var a=0; // 清空
function innerFun() // 內部函數
{
a++;
alert(a);
}
return innerFun; // 注意這里 核心
}
var obj=outerFun(); // 1 2
obj(); obj();
var obj2= outerFun();
obj2(); obj2(); // 1 2
// 結果是 什么 屯曹?
function outerFun() // 外部函數
{
var a=0; // 清空
return function() // 內部函數
{
a++;
alert(a);
}
}
</script>
結果是1,2 1,2
這些外部執(zhí)行域的非持久型變量神奇地保留他們在閉包最初定義(或創(chuàng)建)時的值。
閉包的優(yōu)缺點 :
優(yōu)點:不產生全局變量惊畏,實現屬性私有化恶耽。
缺點:閉包中的數據會常駐內存,在不用的時候要刪掉否則會導致內存溢出陕截。
閉包原理★★★★★
<script>
function outFun() {
var num = 10;
function inFun() { // 內部的函數可以使用外部的函數 變量
console.log(num);
}
return inFun; // 注意:不帶括號2道狻!不帶括號返回函數體农曲,帶括號返回函數值
}
var obj = outFun();
// obj = function inFun() { console.log(num)}
obj();
</script>
閉包的價值——傳參
閉包的傳參:
<script>
function Fun(x) {
return function(y) {
console.log(x+y);
}
}
var obj = Fun(4);
// 相當于 obj = function() {console.log(x)}
obj();
obj(2);
</script>
結果:NAN 6
事件傳遞參數案例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
div {
position: absolute;
left: 0;
background-color: pink;
width: 100px;
height: 100px;
}
</style>
</head>
<body>
<button id="btn1">右走</button>
<button id="btn2">左走</button>
<div id="box"></div>
</body>
</html>
<script>
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var box = document.getElementById("box");
/*之前的寫法:
var speed = 5;
btn1.onclick = function() {
box.style.left = box.offsetLeft + speed+ "px";
}
btn2.onclick = function() {
box.style.left = box.offsetLeft + speed+ "px";
}*/
/* btn1.onclick = function() {
move(5);
}
btn2.onclick = function() {
move(-5);
}
function move(speed) {
box.style.left = box.offsetLeft + speed + "px";
}*/
function move(speed) {
return function() {
box.style.left = box.offsetLeft + speed + "px";
}
}
btn1.onclick = move(5);
btn2.onclick = move(-5);
</script>
閉包版本的TAB欄切換
備注:<a href="http://www.reibang.com/p/7658c093e411" target="" >不用閉包的已于JS(四)介紹過 </a>
多個tab欄(閉包)
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
*{margin:0;padding:0;}
ul{list-style:none;}
.box {
width: 350px;
height: 300px;
border:1px solid #ccc;
margin: 100px auto;
overflow: hidden;
}
.mt span {
display: inline-block;
width: 80px;
height: 30px;
background-color: pink;
text-align: center;
line-height: 30px;
cursor: pointer;
}
.mt span.current {
background-color: purple;
}
.mb li {
width: 100%;
height: 270px;
background-color: purple;
display: none;
}
.mb li.show {
display: block;
}
</style>
<script>
window.onload = function(){
//要想多個盒子不相互影響 社搅,我們可以通過id 給他們分開
//封裝tab欄切換函數
function tab(obj){
var target = document.getElementById(obj);
var spans = target.getElementsByTagName("span");
var lis = target.getElementsByTagName("li");
for(var i=0;i<spans.length;i++)
{
// spans[i].index = i;
spans[i].onmouseover = function (num) {
return function(){
for(var j=0; j<spans.length;j++)
{
spans[j].className = "";
lis[j].className = "";
}
spans[num].className = "current";
lis[num].className = "show";
}
}(i);
}
}
tab("one");
tab("two");
tab("three");
}
</script>
</head>
<body>
<div class="box" id="one">
<div class="mt">
<span class="current">新聞</span>
<span>體育</span>
<span>娛樂</span>
<span>八卦</span>
</div>
<div class="mb">
<ul>
<li class="show">新聞模塊</li>
<li>體育模塊</li>
<li>娛樂模塊</li>
<li>八卦模塊</li>
</ul>
</div>
</div>
<div class="box" id="two">
<div class="mt">
<span class="current">新聞</span>
<span>體育</span>
<span>娛樂</span>
<span>八卦</span>
</div>
<div class="mb">
<ul>
<li class="show">新聞模塊</li>
<li>體育模塊</li>
<li>娛樂模塊</li>
<li>八卦模塊</li>
</ul>
</div>
</div>
<div class="box" id="three">
<div class="mt">
<span class="current">新聞</span>
<span>體育</span>
<span>娛樂</span>
<span>八卦</span>
</div>
<div class="mb">
<ul>
<li class="show">新聞模塊</li>
<li>體育模塊</li>
<li>娛樂模塊</li>
<li>八卦模塊</li>
</ul>
</div>
</div>
</body>
</html>
tab欄(閉包節(jié)流)
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
*{margin:0;padding:0;}
ul{list-style:none;}
.box {
width: 350px;
height: 300px;
border:1px solid #ccc;
margin: 100px auto;
overflow: hidden;
}
.mt span {
display: inline-block;
width: 80px;
height: 30px;
background-color: pink;
text-align: center;
line-height: 30px;
cursor: pointer;
}
.mt span.current {
background-color: purple;
}
.mb li {
width: 100%;
height: 270px;
background-color: purple;
display: none;
}
.mb li.show {
display: block;
}
</style>
<script>
window.onload = function(){
//要想多個盒子不相互影響 ,我們可以通過id 給他們分開
//封裝tab欄切換函數
function tab(obj){
var target = document.getElementById(obj);
var spans = target.getElementsByTagName("span");
var lis = target.getElementsByTagName("li");
for(var i=0;i<spans.length;i++)
{
// spans[i].index = i;
var timer = null;
spans[i].onmouseover = function (num) {
return function(){
clearTimeout(timer);
timer = setTimeout(function(){
for(var j=0; j<spans.length;j++)
{
spans[j].className = "";
lis[j].className = "";
}
spans[num].className = "current";
lis[num].className = "show";
},300)
}
}(i);
spans[i].onmouseout = function() {
clearTimeout(timer);
}
}
}
tab("one");
tab("two");
tab("three");
}
</script>
</head>
<body>
<div class="box" id="one">
<div class="mt">
<span class="current">新聞</span>
<span>體育</span>
<span>娛樂</span>
<span>八卦</span>
</div>
<div class="mb">
<ul>
<li class="show">新聞模塊</li>
<li>體育模塊</li>
<li>娛樂模塊</li>
<li>八卦模塊</li>
</ul>
</div>
</div>
<div class="box" id="two">
<div class="mt">
<span class="current">新聞</span>
<span>體育</span>
<span>娛樂</span>
<span>八卦</span>
</div>
<div class="mb">
<ul>
<li class="show">新聞模塊</li>
<li>體育模塊</li>
<li>娛樂模塊</li>
<li>八卦模塊</li>
</ul>
</div>
</div>
<div class="box" id="three">
<div class="mt">
<span class="current">新聞</span>
<span>體育</span>
<span>娛樂</span>
<span>八卦</span>
</div>
<div class="mb">
<ul>
<li class="show">新聞模塊</li>
<li>體育模塊</li>
<li>娛樂模塊</li>
<li>八卦模塊</li>
</ul>
</div>
</div>
</body>
</html>
屏幕縮放事件
(非閉包):
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="demo"></div>
</body>
</html>
<script>
var num = 0;
var demo = document.getElementById("demo")
window.onresize = function() { // ie8 等瀏覽器 每觸發(fā)一次 乳规,執(zhí)行兩次
num++;
demo.innerHTML = window.innerWidth || document.documentElement.clientWidth; // 得到當前的屏幕寬度
console.log(num);
}
</script>
(閉包版的函數節(jié)流):
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="demo"></div>
</body>
</html>
<script>
var num = 0;
var demo = document.getElementById("demo")
window.onresize = throttle(function(){
demo.innerHTML = window.innerWidth || document.documentElement.clientWidth;
num++;
console.log(num);
},300);
function throttle(fn,delay) { // 閉包 節(jié)流
var timer = null;
return function() {
clearTimeout(timer);
timer = setTimeout(fn,delay);
}
}
</script>
對象(object)
對象是什么形葬?
基本數據類型 string number boolean null undefined
Array 對象
對象數據類型: 對象就是帶有屬性和方法的 數據類型
但是有個問題, 我們想要某些屬性或者方法的時候暮的,用數組不合適笙以。
我們想要自己id屬性和方法 。 要求這個一定是個對象才行冻辩。
1/聲明對象
我們有兩種聲明對象的方式.
var obj = new Object();
但是我們更提倡用第二種方法: 字面量式聲明對象
var obj = {};
2/使用對象
聲明對象的完整源碼:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
</body>
</html>
<script>
// var obj = new Object();
var obj = {}; // 聲明對象
obj.name = "劉德華"; // 屬性
obj.age = 55;
obj.showName = function() { // 聲明方法 方法一定帶有 ()
alert("俺是劉德華");
}
obj.showAge = function() {
alert("俺今年18歲");
}
console.log(obj.name); // 調用屬性
console.log(obj.age);
obj.showName(); // 調用方法
obj.showAge();
</script>
3/面向對象
面向對象里面:類和對象
類是對象的抽象猖腕,而對象是類的具體實例
一切事物皆對象 JavaScript 一切皆對象
類 和 對象
對象 女朋友
小胡 你有對象了嗎? 泛指 女朋友
旁邊坐的那個女生是你對象嗎恨闪? 特指 某一個女朋友
大家喜歡吃蘋果嗎倘感? 泛指 類
你手里的那個蘋果甜嗎? 特指 對象 (具體的實例)
面向對象的特性
-1. 抽象
抽象就是忽略一個主題中與當前目標無關的那些方面咙咽,以便更充分地注意與當前目標有關的方面老玛。
-2. 封裝
封裝是把過程和數據包圍起來,對數據的訪問只能通過已定義的界面
-3. 繼承
-4. 多態(tài)
多態(tài)是指兩個或多個屬于不同類的對象钧敞,對于同一個消息(方法調用)作出不同響應的方式
4/new
新的 我們經常利用new 關鍵字 去聲明新的對象
javascript
new運算符的作用是創(chuàng)建一個對象實例蜡豹。這個對象可以是用戶自定義的,也可以是帶構造函數的一些系統(tǒng)自帶的對象溉苛。
new 關鍵字可以讓 this 指向新的對象
所謂"構造函數"镜廉,其實就是一個普通函數,但是內部使用了this變量愚战。對構造函數使用new運算符桨吊,就能生成實例威根,并且this變量會綁定在實例對象上。
new關鍵字來聲明:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
</body>
</html>
<script>
function Person(name,age) { // 構造函數 就是一個普通函數 為了和普通函數區(qū)別 第一個字母大寫
this.name = name;
this.age = age;
this.showName = function() {
alert("我的名字是" + name);
}
this.showAge = function() {
alert("我的年齡是"+ age);
}
}
var demo = new Person("劉德華",18);
var demo1 = new Person("劉德華",18);
console.log(demo.name); // 提倡用調用
console.log(demo["name"]);
console.log(demo.age);
// demo.showName();
/* alert(demo.showName);
alert(demo1.showName);*/
alert(demo.showName == demo1.showName);
</script>
5/prototype
共同的 相同的 部分
主要解決:函數因為使用非常非常多视乐,重復執(zhí)行效率太低洛搀。
類.prototype.方法 = function() {} 具體格式
可以把那些不變的屬性和方法,直接定義在prototype對象上
使用方法:
類名.prototype.方法
原型的面向對象:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
</body>
</html>
<script>
function Person(name,age) { // 構造函數
this.name = name; // 只寫屬性
this.age = age;
}
Person.prototype.showName = function() { // 用的共同的父親
alert("我的名字是"+ this.name);
}
Person.prototype.showAge = function() {
alert("我的名字是"+ this.age);
}
var demo = new Person("劉德華",15);
var demo1 = new Person("劉德華",15);
demo.showName();
alert(demo.showName === demo1.showName);
</script>
(面向對象版本)下拉菜單:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>無標題文檔</title>
<style type="text/css">
*{ padding:0; margin:0; list-style:none;}
.all{ width:330px; height:30px; background:url(img/bg.jpg) no-repeat; margin:100px auto; line-height:30px; text-align:center; padding-left:10px; margin-bottom:0;}
.all ul li{ width:100px; height:30px; background:url(img/libg.jpg); float:left; margin-right:10px; position:relative; cursor:pointer;}
.all ul ul{ position:absolute; left:0; top:30px; display:none;}
</style>
</head>
<body>
<div class="all" id="list">
<ul>
<li>一級菜單
<ul>
<li>二級菜單</li>
<li>二級菜單</li>
<li>二級菜單</li>
</ul>
</li>
<li>一級菜單
<ul>
<li>二級菜單</li>
<li>二級菜單</li>
<li>二級菜單</li>
</ul>
</li>
<li>一級菜單
<ul>
<li>二級菜單</li>
<li>二級菜單</li>
<li>二級菜單</li>
</ul>
</li>
</ul>
</div>
</body>
</html>
<script>
// 獲取對象 遍歷對象操作 顯示模塊 隱藏模塊
function List(id) { // 獲取對象
this.id = document.getElementById(id); // 取 id 值
this.lis = this.id.children[0].children; // 獲取一級菜單所有的li
}
// init 初始化
List.prototype.init = function() { // 遍歷所有的li 顯示和隱藏
var that = this;
for(var i=0;i<this.lis.length;i++)
{
this.lis[i].index = i;
this.lis[i].onmouseover = function() {
that.show(this.children[0]); // 顯示出來
}
this.lis[i].onmouseout = function() {
that.hide(this.children[0]); // 隱藏起來
}
}
}
// 顯示模塊
List.prototype.show = function(obj) {
obj.style.display = "block";
}
// 隱藏模塊
List.prototype.hide = function(obj) {
obj.style.display = "none";
}
var list = new List("list"); // 實例化了一個對象 叫 list
list.init();
</script>
下拉菜單的案例素材獲扔拥怼:
鏈接:http://pan.baidu.com/s/1slQw0uL 密碼:zvlt