一 项目代码编写规范
1.在写js代码当中,我们采用的是模块化处理,页面中显示的每个显示块我们都当做一个模块来处理,那么我们在编写对应块的代码的时候,我们一般采用面向对象的方法。例如如下图所示:
在我们写js中:
我们一般会写成fn={
new:{
api:{
id:"string类型",
url:"调用接口的地址"
},
init:function(){
//页面初始化的方法,一般为动态创建html模板,显示页面原始数据
},
bind:function(){
//页面每个模块所需要执行的方法,比如播放声音,页面的跳转,下载功 能等等
},
cache:function(){
//需要做到数据缓存的话,那么我们需要做到数据缓存,比如声音的缓存
}
},
hot:{
api:{
id:"string类型",
url:"调用接口的地址"
},
init:function(){
//页面初始化的方法,一般为动态创建html模板,显示页面原始数据
},
bind:function(){
//页面每个模块所需要执行的方法,比如播放声音,页面的跳转,下载功 能等等
},
cache:function(){
//需要做到数据缓存的话,那么我们需要做到数据缓存,比如声音的缓存
}
},
}
上面的api相当于对象new和pop的属性,而init,bind,cache相当于这个对象的方法。
在js当中由此我什么是面向对象以及创建对象的几种方式:
面向对象是把属性和操作方法放在一起作为一个相互依存的整体—对象,就是拥有类的概念,基于类可以创建多个实例对象,一般局域封装,继承,多态的特性。
1.工厂方式(创建一个函数,在函数内部创建一个对象,并且返回这个对象,即是工厂方式),我们上述的方法是面向字面量的方法,如果变成是工厂方法的话,那么即使
function creatGongchang(api, “对应html模板",“对应模块需要传入的数据”, wrap ) {
var obj = new Object();
obj.api = api;
obj.init=function(){
var html = ““;
for(var i in data) {
html+=“对应模块需要传入的数据”;
}
wrap.replace(html);
}
obj.bind = function(){
//对应的绑定方法
},
obj.cache = function(){
//需要缓存的数据
}
}
var hot = creatGongchang(api, “对应html模板",“对应模块需要传入的数据”, $('.hot'));
var pop = creatGongchang(api, “对应html模板",“对应模块需要传入的数据”, $('.pop'));
2.构造函数的方式
任何函数,只要通过new操作符调用就是构造函数,反之就是普通函数。
创建一个新的函数会经历以下四个步鄹:
(1) 创建一个新对象
(2) 将构造函数的作用域付给一个新对象,this就指向了这个新对象
(3) 执行函数中的代码,返回新对象
function Module(api, "对应的模板字符串", data, wrap){
this.api = api;
this.init=function(data, "对应的模板字符串"){
var html = "";
for(var i in data){
html+= "对应的模板字符串";
}
wrap.repace(html);
}
this.bind=function(){
//对应的该模块的绑定方法
wrap.on("click", function(){
})
}
this.cache=funcion(){
}
}
var hot = new Module(api, "对应的模板字符串", data, $(".hot"));
3.原型模式 首先介绍一下prototype(原型)属性,我们创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。
PS:JS中万物皆对象,但分为两大类:普通对象和函数对象。所有的函数对象都有一个prototype属性,普通对象是没有prototype属性的,只有proto。
function Moulde(api, "对应的模板字符串", data, $(".hot")){
Moulde.prototype.api = api;
Moulde.prototype.init= function(){
Module.prototype.bind=function(){
Module.prototype.cache=function(){
}
}
var hot = Moulde(api, "对应的模板字符串", data, $(".hot"));
4 组合使用构造函数模式和原型模式
function createPerson(name,age,job){
this.name = name;
this.age = age;
this.job = job;
}
createPerson.prototype.sayName = function(){
alert(this.name);
};
var tanya =new createPerson("tanya","30","female");
tanya.sayName();
二.关于函数的传参问题
在js当中,数据类型可以分为两种:
基本类型值:比如(1)undefined, null, 布尔值,Number, String.
引用类型:(2 ) 数组,对象,函数。
关于变量的复制
我们知道,js中变量的基本类型和引用类型的保存方式是不同的,这也就导致了变量复制时也就不同了,如果一个变量向另外一个变量复制基本类型时,前者的值会拷贝给后者,且两着的存储空间完全独立,不会相互影响。
var num1 = 10;
var num2 = num1;
num2 = 20;
console.log(num1); //10
console.log(num2); //20
关于引用类型的拷贝
var obj1 = {
name : “bob“
}
var obj2 = obj1;
obj2 = {
name:"jack"
}
console.log(obj1); //jack
那么这是什么原因呢?
这就会考虑到我们的引用类型,复制对象时并不会在堆内存中新生成一个一模一样的对象,只是多了一个保存指向这个对象指针的变量罢了。将obj1的值复制给obj2,而这个值的副本实际上是一个指针,这个指针指向存储在堆中的一个对象,也就是说创建了一个新的内存地址传给了obj2,obj1和obj2两个变量同时指向了同一个Object,当去改变这个对象时,他们的值都会改变,也就是说他们中任何一个作出的改变都会反映在另一个身上。在此处,我们就会考虑到深浅拷贝的问题,如果我们只想复制这个对象,改变这个对向的值并不影响被拷贝的对象,那么我们叫这个对象为深拷贝。那么怎么才能深拷贝呢?
对象的深度拷贝就是把对象的属性和方法遍历一遍,付给一个新的对象;
重点内容函数的值传递
所有函数的参数都是按值传递的,也就是说把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。所以如果能理解变量的复制,那么参数的传递也就很简单了。还是先从基本类型举例说明吧。
复制代码
var count = 10;
function num(num1) {
num1 = 1;
return num1;
}
var result = num(count);
console.log(result); //1
console.log(count) //10
//并没有相互的影响,如果你想改变count,那么
function num(num1){
count++;
}
num(count);
//函数能够读取全局变量,修改全局变量
这个例子很容易理解,实际就是创建了一个count的副本,然后把count的值传入参数中,因为函数中定义了参数的值,所以1就将10覆盖了,最后的result返回1,而count并未发生变化。看一个有关传递对象的例子。
var person = {
name : "Tom"
};
function obj(peo){
peo.name = "Jerry";
return peo;
}
var result = obj(person);
console.log(result.name);// Jerry
console.log(person.name);// Jerry
在上面的例子中,把person复制传入obj()中,peo和person指向了同一个对象,而在peo中修改了name属性,其实修改了它们共同指向的对象的name属性,相对应的外部person所引用的name属性也就改变了,所以打印出来的为Jerry。其实这个乍一看,感觉引用类型的参数是按照引用传递的
var person = {
name : "Tom"
};
function obj(peo){
peo = {
name : "Jerry"
};
return peo;
}
var result = obj(person);
console.log(result.name);// Jerry
console.log(person.name);// Tom
上面的例子中,在函数中重新定义了一个对象,也就是现在堆内存中有两个对象,外部的person指向的是老的对象,被传入参数后指向的是新定义的对象,所以调用后返回的值是新定义的对象的值。如果是参数是按引用传递的,那么person.name打印出来的结果为Jerry,从这点可以得出参数是按值传递的(有的地方叫做按共享传递)。
三.关于数组
js的数组中有操作数组的方法,数组的增删改查,在js编程当中也会经常遇见;
1.在这里普及一下栈方法,栈先进后出,队列先进先出;数组的push()方法和shift()方法相对应;
对于shift方法,他能够删除数组第一向并返回该项值,并且数组长度减一,
push方法向数组末尾添加值并且返回添加个数
var arr = new Array();
var count = arr.push("red", "color");
console.log(arr); //"red","color";
console.log(count)//2;
count = arr.push("bule");
console.log(count); //1
同时,ECMAscript还为数组提供了一个unshift()方法,它在数组前面添加任意一个项并且返回数组新数组的长度;
2.slice方法和splice方法。
arr1 = arr.slice(1,4); //保留数组1,4的数组,slice(1,4),起始项是1,末尾项是4
arr2 = arr.slice(1); //从1位开始截取数组
splice方法
(1)删除功能:splice(0,2),splice指定两个参数,第一个参数是数组删除初始项,第二个参数师数组结束项
(2)插入:可以向指定位置插入任意数量的项,只需要提供三参数
(3)slice(2,0, “red”, “blue”)//第一项,插入最开始的位置,第二项,需要删除的项,第三项,需要插入的项
3.数组的查找方法(indexof()和lastindexof())
此外数组还有迭代方法 every,filter,forEach等等
四.关于ajax
一般来说,我们会常常用到ajax与后台进行数据交互,所以对于我们来说,
kAjax : function(url,param,success,error,tag){
// copy并去空值
var param = $.removeEmpty(param, true);
$.ajax({
type: "get",
cache: false,
async: true,
url: url,
data: param,
dataType: "jsonp",
jsonpCallback:"jsonpCallback"+Math.round(Math.random()*10000),
success: function(json){
if(json.status == '4'){
alert('未登陆');
return;
}
if(json.status == '1'){
typeof success == 'function' && success(json);
}else{
typeof error == 'function' && error(json.message);
console.log(json.message);
}
},
error: function(err){
console.log(err);
}
});
}
上面为我们封装的和后台交互的一个封装函数,我们只需要采取这个封装函数就可以与后台进行交互,首先是:
1,跨域类型,jsonp只能有get跨域
2.url:你需要请求数据的地址,
3.cache:是否进行缓存
4.data:你需要传入的向后台请求参数的对象
5.dataType:“jsonpCallback”,
6.sussuss:成功的回调函数
7.error:错误的回调函数