前端基本功--网页特效6 12.13
- apply的一些其他巧妙用法
(1)Math.max 可以实现得到数组中最大的一项:
因为Math.max不支持Math.max([param1,param2])也就是数组,但是它支持Math.max(param1,param2...),所以可以根据apply的特点来解决 var max=Math.max.apply(null,array),这样就轻易的可以得到一个数组中的最大项(apply会将一个数组转换为一个参数接一个参数的方式传递给方法)
这块在调用的时候第一个参数给了null,这是因为没有对象去调用这个方法,我只需要用这个方法帮我运算,得到返回的结果就行,所以直接传递了一个null过去。
用这种方法也可以实现得到数组中的最小项:Math.min.apply(null,array)
(2)Array.prototype.push可以实现两个数组的合并
同样push方法没有提供push一个数组,但是它提供了push(param1,param2...paramN),同样也可以用apply来转换一下这个数组,即:
1.var arr1=new Array("1","2","3");
2.var arr2=new Array("4","5","6");
3.Array.prototype.push.apply(arr1,arr2); //得到合并后数组的长度,因为push就是返回一个数组的长度
也可以这样理解,arr1调用了push方法,参数是通过apply将数组转换为参数列表的集合
通常在什么情况下,可以使用apply类似Math.max等之类的特殊用法:
一般在目标函数只需要n个参数列表,而不接收一个数组的形式,可以通过apply的方式巧妙地解决这个问题。
- 瀑布流
思路大概就是得到当前的屏幕宽度/每个图的宽度,得到每行有几个,如果是第一行 自动铺开,若果不是就判断每行最短的图,把图片先添加到最短的图下面,左边距为上面图的宽度,再把高度加上自身高度,使其不重复!
然后开始自动加载:当最后一张的上边距小于页面滚动高度加上页面高度开始自动加载!自动加载函数中要自动添加每行的元素。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS</title>
<style>
/*使用通配符将内外边距都设置为零, 这样看着好看*/
*{
margin: 0px;
padding: 0px;
}
/*将主容器的布局方式设置为相对布局*/
#contianer{
position: relative;
}
.box{
padding: 5px;
float: left;
}
/*将承载图片的容器定制颜色及边框大小和圆角*/
.boximg{
padding: 5px;
box-shadow: 0 0 5px #ccc;
border: 1px solid #cccccc;
border-radius: 5px;
}
/*定制图片尺寸*/
.boximg img{
width: 250px;
height: auto;
}
</style>
</head>
<body>
<div id="container">
<div class="box">
<div class="boximg">
<img src="images/slidepic1.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic2.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic3.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic4.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic5.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic8.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic9.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic9.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic8.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic9.jpg">
</div>
</div> <div class="box">
<div class="boximg">
<img src="images/slidepic8.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic9.jpg">
</div>
</div> <div class="box">
<div class="boximg">
<img src="images/slidepic8.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic9.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic5.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic8.jpg">
</div>
</div>
<div class="box">
<div class="boximg">
<img src="images/slidepic9.jpg">
</div>
</div>
</div>
</body>
</html>
<script type="text/javascript">
window.onload = function(){
dingwei("container","box");
//自动加载,最后一个长图出来之前开始加载
//模拟数据传输啦(通常使用json)放在外面
var imgs ={
"json":[
{"src":"slidepic9.jpg"},
{"src":"slidepic8.jpg"},
{"src":"slidepic7.jpg"},
{"src":"slidepic3.jpg"},
{"src":"slidepic2.jpg"},
{"src":"slidepic1.jpg"},
]};
window.onscroll = function(){
if(check()){
var cparent = document.getElementById("container");
for(var i=0;i<imgs.json.length;i++){
var ccontent = document.createElement("div");
ccontent.className = "box";
cparent.appendChild(ccontent);
//1
var boximg = document.createElement("div");
boximg.className = "boximg";
ccontent.appendChild(boximg);
//2
var img = document.createElement("img");
img.src = "images/"+imgs.json[i].src;
boximg.appendChild(img);
}
dingwei("container","box");//滚动开启定位函数
}
}
}
function check(){
var checkparent = document.getElementById("container");
var checkcontent = getAllChirld(checkparent,"box");
var lastheight = checkcontent[checkcontent.length-1].offsetTop;
//滚动高度+当前页面高度大于z最后一张图片距离顶部的距离就要加载了
var scrollTop = document.documentElement.scrollTop||document.body.scrollTop;
var pageheight = document.documentElement.clientHeight||document.body.clientHeight;
// console.log(lastheight+":"+(scrollTop+pageheight+"px"));
if(lastheight<scrollTop+pageheight){
return true;
}
}
// 定位的函数
function dingwei(parent,content){
var cparent = document.getElementById(parent);
var ccontent = getAllChirld(cparent,content);
var imgwidth = ccontent[0].offsetWidth;
var num = Math.floor(document.documentElement.clientWidth/imgwidth);
cparent.style.cssText = "width:"+imgwidth*num+"px;margin:0 auto";
var heightarr = [];
for(i=0;i<ccontent.length;i++){
if(i<num){
heightarr[i] = ccontent[i].offsetHeight;
}
else{
var minheight = Math.min.apply(null,heightarr);
var minindex = getminheight(heightarr,minheight);
ccontent[i].style.position = "absolute";
ccontent[i].style.top = minheight+"px";
ccontent[i].style.left = ccontent[minindex].offsetLeft+"px";
heightarr[minindex] = heightarr[minindex] + ccontent[i].offsetHeight;
//很重要,最短高度下的那张图片的左边距离是最小的那张的左边距,为了让下面图不重叠在一起,最短图下的高度值等于自己的高度加上上面图片高度
}
}
}
// 获取最小高度
function getminheight(heightarr,minheight){
for(var i in heightarr){
if(heightarr[i] == minheight){
return i;
}
}
}
// 得到所有box
function getAllChirld(parent,content){
var contentarr = [];
var allcontent = parent.getElementsByTagName("*");
for(var i=0;i<allcontent.length;i++){
if(allcontent[i].className == content){
contentarr.push(allcontent[i]);
}
}
return contentarr;
}
</script>
一、函数和作用域
- 两种定义函数的区别
fun(); // 调用函数 放到哪个位置都可以
function fun() {
console.log(3);
}
var fn = function() {
console.log(4);
}
fn(); // 调用函数 必须再函数声明的下面 先声明后使用
- 全局变量和局部变量
内部变量是受保护的
全局变量:都可以使用
二、闭包
- 可以用一个函数去访问另一个函数内部的变量的方式就是闭包。
function out(){
var num = 10;
function inn(){
console.log(num);
}
return inn;
}
console.log(out());
demo = out();
demo();
demo函数就是一个闭包。
- 优点:不产生全局变量,实现属性私有化。
缺点:闭包中的数据会常驻内存,在不用的时候要删掉否则会导致内存溢出。 - 事件传递参数
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var box = document.getElementById("box");
btn1.onclick = move(5);
btn2.onclick = move(-5);
function move(speed) {
return function(){
box.style.left = box.offsetLeft+speed+"px";
}
}
- 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++){
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");
- 每次缩放屏幕发生改变(函数节流)
var num = 0;
var one = document.getElementById("one");
window.onresize = haha(function(){
num++;
one.innerHTML = window.innerWidth || document.documentElement.clientWidth;
console.log(num);
},300);
function haha(fn,time){
var timer = null;
return function(){
clearTimeout(timer);
timer = setTimeout(fn,time);
}
}
//函数节流,每次改变屏幕宽度都发生改变
三、对象
- object
基本数据类型: string number boolean null undefined
对象数据类型:对象就是带有属性和方法的 数据类型
Array 对象
var num = 10; // 变量
var arr = []; // 数组
arr.index = 10; // 数组arr 的 一个 index 属性
我们想要某些属性或者方法的时候,用数组不合适。
arr.length
我们想要自己id属性和方法 。 要求这个一定是个对象才行。
- 声明对象
(1)var obj = new Object();
(2) var obj = {};字面量方法,更提倡。
- 使用对象
console.log(obj.name); // 调用属性 console.log(obj.age);
obj.showName(); // 调用方法 obj.showAge();
- 面向对象
js里,一切都是对象
面向对象里面:类和对象
类是对象的抽象,而对象是类的具体实例
特性:
1. 抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。
2. 封装:封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面
3. 继承
4. 多态:多态是指两个或多个属于不同类的对象,对于同一个消息(方法调用)作出不同响应的方式 - new
new运算符的作用是创建一个对象实例。
这个对象可以是用户自定义的,也可以是带构造函数的一些系统自带的对象。
new 关键字可以让 this指向新的对象。
所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。 - prototype
主要解决:函数因为使用非常非常多,重复执行效率太低。
类.prototype.方法 = function() {} 具体格式
这个方法可以被很多对象调用
- 下拉菜单实例
<script>
var list = new List("list");
function List(id){
this.id = document.getElementById(id);
this.lis = this.id.children[0].children;
// console.log(this.lis.length);
}
//获取对象
List.prototype.init = function(){
var that = this;
for(var i=0;i<this.lis.length;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";
}
list.init();
//要在init初始化之后执行函数
</script>