JS代码可以写在三个位置
2.1. <script>标签中
2.2. 引入一个外部的js
新建一个文本文件,文件后缀为js,在这个文本文件中写代码,然后在需要使用这些代码的网页中使用<script></script>(必须是完整标签引入,不能写成自结束<script src=””/>)标签指定src引入。
2.3. JS代码作为特殊属性的值
<!-- 1.<script>标签中 -->
<!-- <script type="text/javascript"> -->
<!-- alert(0); -->
<!-- </script> -->
<!-- 2.引入一个外部的js -->
<!-- <script type="text/javascript" src="index.js"></script> -->
</head>
<body>
<!--3.JS代码作为特殊属性的值 -->
<!-- 建议a标签的href少用# -->
<a href="#" onclick="javascript:alert(1);">a1</a>
<!-- 必须记住的:不使用瞄点的方式 -->
<a href="javascript:;" onclick="javascript:alert(2);">a2</a>
<a href="javascript:void(0);" onclick="javascript:alert(3);">a3</a>
<!-- 如果url地址后面有#,表示执行了一个瞄点 -->
<div id="top">top</div><a href="#footer">footer</a>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<p>0<p>
<div id="footer">footer</div><a href="#top">top</a>
</body>
2.4. 注意点
3.1. 为什么需要函数
JS代码可以直接编写在<script>标签之间或者一个单独JS文件中,这些代码在页面被解析的时候就进行执行。
实际开发中,有的时候我们需要多次执行相同代码,或者在特定的时机执行某段代码,那么函数就可以解决这些问题。
函数可以包装一段代码,并且可以为这段代码取名,名字即为函数名,通过这个函数名可以达到多次调用效果。
3.2. 函数的定义及调用
3.2.1. 如何定义一个函数:
函数默认是添加到window对象里面,
如果同一段script,先调用函数,在定义函数,不会出错
函数如果加了()就是调用
函数是由这样的方式进行声明的:关键字 function、函数名、若干参数[可选]、返回值[可选],以及置于括号中的待执行代码。
function 函数名(参数1,参数2){
//代码
return 返回值;
}
3.2.2. 函数的调用(只要看到函数后面有()就是立即调用)
函数名(参数1,参数2);
<script type="text/javascript">
//函数可以包装一段代码,并且可以为这段代码取名,名字即为函数名,通过这个函数名可以达到多次调用效果。
//声明一个函数
function sayMsg(){
console.debug("你好");
}
//调用函数
sayMsg();
<script/>
3.2.3. 函数参数细节
如果被调用的函数,需要我们传入参数,比如求两数和的函数,调用时我们就需要传入两个数。
其实函数调用时,形参和实参的个数可以不一致,如果没有传入实参,那么值为undefined,如果实参个数大于形参个数,也可以正常执行。
//函数参数细节==================================================
function getSum(num1,num2){
return num1+num2;
}
//传入实参与形参对应.结果是:15
console.debug(getSum(5,10));
//传入实参个数大于形参个数.结果是:15
console.debug(getSum(5,10,25));
//传入实参个数小于形参个数.结果是:NaN
console.debug(getSum(5));
//分析 , num1=5,num2=undefined 由于我们进行的是加法运算,js会自动把非数字的值转换为数字,
//undefined就会转换为数字,所以undefined为NaN,NaN与任何数字做运算都为NaN;
//1.js运算时如果字符串与任何值做加法都是连接字符串; 2.js运算时如果非数字,那么会先把非数字转化为数字.
3.2.4. 函数返回值
返回值:函数代码执行完毕,把运算的结果数据返回,返回的数据就叫返回值。
如果一函数有返回值,无需特殊声明,只需要使用 return 运算符后跟要返回的值即可,如果没有返回值,函数的默认返回值为undefined。
//如果一个函数有返回值,那么就直接在函数体中使用return 返回值.如果没有返回值,不写.
function getAddress(){
//return "武汉某个乡卡卡";
}
console.debug(getAddress()); //如果没有返回值,返回值就是undefined.
4.1. 预编译:
(代码的首行到末尾扫描),如果发现某行代码中声明函数变量,会声明放到最最最最最前面(代码首行);[变量提升]
4.2. 执行:执行的时候才会逐行执行. (赋值在执行期)
//alert(username);//undefined
var username = "张三疯";
//alert(fn);//undefined
var fn = function(){}; //函数表达式
sayHello();
/**
javascript引擎执行过程:
1.预编译:(代码的首行到末尾扫描),如果发现某行代码中声明函数,会声明函数放到最最最最最前面(代码首行);
2.执行:执行的时候才会逐行执行. (赋值在执行期)
**/
//声明函数
function sayHello(){
console.debug("hello");
}
函数运行过程中,JavaScript会自动产生一些特殊对象相当于js的内置对象,不需要我们创建,我们可以使用这些对象干一些有意思的事情。
5.1. 思考
1.JavaScript中函数调用时实参的个数可以与形参的个数不一致,如果少传入参数可能会导致计算结果不正确。
2.目标1:现在需要编写一个函数,该函数接受任意个数的参数(类似于java的可变参数),对传入的参数进行求和。
3.目标2:方法的重载:方法名相同,参数的类型或者参数的个数不一样。
5.2. 对比Java(但是js里面默认没有重载和重写)
【Java里面的内容,比较一下
Override是重写(覆写):方法名称、参数个数,类型,顺序,返回值类型都是必须和父类方法一致的。它的关系是父子关系
Overload是重载:方法名称不变,其余的都是可以变更的。它的关系是同一个类,同一个方法名,不同的方法参数或返回值。
备注:它们都是是Java多态性的不同表现
】
以上场景中问题,都与函数被执行时传入的参数有关,其实在函数被执行的时候会自动创建一个用于描述“参数列表值”的对象。
5.3. arguments
函数中获取参数值,可以通过参数名获取,也可以通过arguments对象来获取;
arguments产生:该对象不是由程序员创建的,而是在javascript执行函数的时候,就会为这个函数创建一个arguments对象,我们可以在函数内部使用这个对象;
arguments对象:包含了本次调用函数时传入的所有参数。该对象为一个“伪”数组。
arguments伪数组:和普通对象一样,只是对象具有通过索引([index])访问成员的功能和访问个数(arguments.length)功能。
arguments对象属性:
length:传入参数的个数。
callee:当前函数对象:返回正被执行的function对象。(已过时)
语法:arguments.callee。
5.3.1. JavaScript中函数调用时实参的个数可以与形参的个数不一致,如果少传入参数可能会导致计算结果不正确。
function sayMsg(name,msg){
//arguments : 函数的参数列表.
//arguments创建 : 该对象不是由程序员创建的,而是在javascript执行函数的时候,
//就会为这个函数创建一个arguments对象,我们可以在函数内部使用这个对象;
if(arguments.length>=2){
console.debug(name+" : "+msg);
}
}
sayMsg("王大锤");
sayMsg("王大锤","呵呵");
5.3.2. 现在需要编写一个函数,该函数接受"任意个数的参数"对传入的参数进行求和。
function getSum(){
//arguments 是一个数组.
var sum;
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
console.debug(getSum(1,5,6,7,8,9));
5.4. 方法的重载:方法名相同,参数的类型或者参数的个数不一样。
5.4.1. 实现类似jQuery的get方法
/**
url,[data],[callback],[type]
url:待载入页面的URL地址
data:待发送 Key/value 参数。
callback:载入成功时回调函数。
type:返回内容格式,xml, html, script, json, text, _default。
**/
function get(url,data,callback,type){
//如果第二参数是一个函数,那么就可以确定传入第二个参数其实应该在第三个位置.
if(typeof data == "function"){
type = callback;
callback = data;
data = undefined;
}
console.debug("url : "+url);
console.debug("data : "+data);
console.debug("callback : "+callback);
console.debug("type : "+type);
}
get("xxx.action",function(){
console.debug("响应函数");
},"json");
5.4.2. jQuery.js:jquery-2.1.1.js p8289
6.1. 一切皆对象
JavaScript中一切皆对象,在JavaScript中我们可以把任何(基本数据)类型当成对象来使用。
比如var num = 3.14159;我们可以调用Number对象上面的toFixed(2)方法来进行小数位的截取。这点于Java中既然不同,Java中的基本数据类型是不能调用方法,只能通过包装类型。
//JavaScript中一切皆对象,在JavaScript中我们可以把任何(基本数据)类型当成对象来使用。
//基本数据类型:number/boolean/string/null(值:null)/undefined(undefined)
//引用数据类型:Object/Array/Regexp/Date/Number/Boolean/String...
//基本数据类型中number.
var num1 = 3.14159;
console.debug(num1.toFixed(2)); //一切皆对象
console.debug(typeof num1);//number
//引用数据类型Number
var num2 = new Number(3.14159);
console.debug(num2.toFixed(2));
console.debug(typeof num2);//object
var b1 = false;
if(b1){
console.debug("能输出我就吃下去");
}
//js 中所有值的真假性: 0,"",undefined,NaN,null,false(基本数据类型的false)为false,其他值都为true.
var b2 = new Boolean(false);
if(b2){
console.debug("会输出.....,坑");
}
6.2. 简单操作
6.2.1. 创建对象
var obj = new 类();
6.2.2. 添加属性/方法
obj.name = "张三";
obj["age"] = 18;
obj.say = function(){
alert(this.name);
}
6.2.3. 删除属性
delete obj.name;
delete obj["age"];
6.2.4. 遍历对象成员
for(var p in obj){
console.debug(p);//p(string)为对象的属性成员名。
}
6.3. JSON对象和JSON字符串
{key1:value,key2:value....};
var obj = {name:"张三",age:18};
<script type="text/javascript">
//创建json对象
var jsonObject1 = {
name : "xxx",
age : 20
};
//创建json字符串,后台action向前台传递的字符串参数
//标准json字符串:key必须写"",不是‘‘,如果值不是为布尔,数值,也必须写""
var jsonString = ‘{"name":"xxx","age":20}‘;
// var jsonString = "{‘name‘:‘xxx‘,‘age‘:20}";JSON.parse报错
// 怎样把json字符串转化为json对象
var jsonObject2 = eval("(" + jsonString + ")");//可以转换不标准的json字符串
var jsonObject3 = JSON.parse(jsonString);//只能转换标准的json字符串
console.debug(jsonObject1);
console.debug(jsonObject2);
console.debug(jsonObject3);
</script>
6.4. 迭代对象成员(属性+方法)
/**
for(var p in obj){
p:代表属性名
obj:代表被迭代的对象
}
**/
for(var p in obj){
console.debug(obj[p]); // -> obj["name"] p = name;
// -> obj["address"] p = address;
//....
//....
}
6.5. 对象属性拷贝
var obj1 = {
name : "gg",
address : "yyy",
age : "18",
sex : "man"
};
var obj2 = {
name : "mm",
sex : "woman"
};
//拷贝属性 - > 逗逼方式
/* obj2.address = obj1.address;
obj2.age = obj1.age;
obj2.sex = obj1.sex; */
//拷贝属性
for(var p in obj1){
//判断obj2中是否存储这个属性.
if(!obj2.hasOwnProperty(p)){
obj2[p] = obj1[p]; //obj2["address"] = obj1["address"]; p = "address"
}
}
引用JavaScript中最经典的一句话,一切皆对象,函数其实也是一个对象,这点让很多学习JavaScript的人感到无比的困惑,但是JavaScript的确如此。
7.1. 函数定义方式:这种定义方式非常的常见。
function my(){
}
7.2. 函数对象形式:创建函数对象方式,很诡异,但是的确可行。
var add2 = new Function("a", "b","return a + b");
7.3. 代码
<script type="text/javascript">
//函数有2种定义方式
//第一种:常用
function add(a, b) {
return a + b;
}
console.debug(add(1, 2));//3
//第二种:不常用
var add2 = new Function("a", "b","return a + b");
console.debug(add2(1, 2));//3
//既然函数也是对象,添加属性
add.age=20;
console.debug(add.age);//20
add.name="张久万";
console.debug(add.name);//add,函数的name属性是一个只读的属性,值为函数本身名称
name="xxx";
console.debug(window);
console.debug(name);//默认值是(空字符串) ,打印name属性本身是打印window.name,而window.name默认值是(空字符串)
</script>
7.4. jQuery
<script type="text/javascript" src="jquery-1.11.1.js"></script>
<script type="text/javascript">
$(function(){
//console.debug( $.trim(" a ") );//看成对象来使用
//console.debug( $("#myh1") );//看成函数来使用
});
</script>
</head>
<body>
<h1 id="myh1">全连不休</h1>
</body>
8.1. this使用场景:对函数或方法所在的那个对象进行操作;
this指向的是谁?”谁调用该函数,this就代表谁”
<script type="text/javascript">
var obj = {
name : "王二花"
};
//showName默认是属于window对象
function showName() {
console.debug(this.name);
}
// this指向的是谁?”谁调用该函数,this就代表谁” :window
window.showName();//默认是空字符串
//把window对象的showName函数赋值给obj的getName函数
obj.getName = window.showName;//一定不能写()
//调用obj的getName函数
// this指向的是谁?”谁调用该函数,this就代表谁” :obj
obj.getName();//王二花
</script>
8.2. 修改函数中this
一般后面写代码很少修改函数中this,面试可能被问到,看jQuery源码。
函数也是对象,函数对象中存在两个特别有趣的方法,可以修改this。
call(thisObject,args1,args2...)第2-n个参数一个一个的写
apply(thisObject,[args1,args2])第2个参数是数组
call,apply方法都是调用函数,于函数名()直接调用不同,这个两个方法可以修改函数运行时中的this.
call,apply区别:第一个参数总是指函数运行时的this,call从第二参数开始都为调用函数的参数,而apply,第二个参数为一个数组,该数组就是调用函数的所有参数。
window.msg = "你牛逼";
var obj = {
msg : "我也不赖..."
};
function sayMsg(a,b){
console.debug(this.msg+" 参数:"+a+","+b);
}
//函数也是一个对象,既然是对象,那么这个对象上面就可以有一些方法.
/**
函数对象的方法:
call(thisObject,arg1,arg2..argN)
thisObject:函数执行时,this指向谁.如果不写默认为window.
arg1,arg2...argN代表调用函数时传入参数.
apply(thisObject,[arg1,arg2..argN])
thisObject:函数执行时,this指向谁.如果不写默认为window.
[arg1,arg2..argN] : 函数执行时,传入参数列表,注意是一个数组.
call和apply作用都是让我们的函数执行,其实就等同与 " 函数() "
call和apply主要用于执行一个函数时修改函数中的this.
**/
sayMsg.call(window,"www","ttt");
sayMsg.apply(obj,["www","ttt"]);
//call ,apply的使用
var n1 = new Number(123);
var n2 = 123;
var n3 = new Date();
//jquery可以获取变量的类型.
console.debug($.type(n1));
console.debug($.type(n2));
console.debug($.type(n3));
var obj = {};
alert(obj.toString.call(n1));
//n1是一个Number对象,由于Number的toString被复写过,
//toString的结果是Number的值,如果我想知道类型,我们可以使用object对象的toString.
JavaScript中没有为我们提供像Java中定义类的关键字class。JS中定义类只需要定义这个类的构造函数即可;
JavaScript中没有为我们提供像Java中定义类的关键字class。
JS中定义类只需要定义这个类的"构造函数"即可; 构造函数与普通函数没区别.
只要是类,类名就是首字母大写。
//定义了一个类的构造函数
function User(name,age){
//构造函数中this,就是实例对象
//如果要为对象添加属性,那么需要使用 "this.属性名 = 值;"
this.name = name;
this.age = age;
this.getName = function(){
return this.name;
};
}
//通过new创建 实例对象.
var u1 = new User("大明",50);
console.debug(u1.getName());
var u2 = new User("小明",30);
console.debug(u2.getName());
10.1. 对象u内部结构
10.2. 对象实例u是由两部分组成
10.2.1. 对象自定义属性部分
10.2.2. 对象原型部分,对象的原型也是一个对象,同类型原型部分一样
验证对象的原型也是一个对象
alert(u.__proto__); //[object Object]
验证同类型原型部分一样:实例了2个User对象
u.__proto__===u2.__proto__ true
u.__proto__===User.prototype true
/**
对象实例是由两部分组成:
1.对象自定义属性部分
2.对象原型部分,alert(u.__proto__);对象的原型也是一个对象. (同类型原型部分一样)
**/
function User(name, age, address) {
this.name = name;
this.age = age;
this.address = address;
}
var u = new User("城灌溪", 28, "cd");
/*
对象属性访问过程:
1.对象访问属性时首先会在对象自定义属性部分查找,如果自定义属性部分存在那么就使用;
2.如果访问的属性在自定义部分没有找到,那么就会到对象 的"原型对象(__proto__)"上面查找,有就使用.
3.如果 "原型对象"没有,那么会在"原型对象"的"原型对象"上面 查找对应属性,如果有就使用.
*/
console.debug(u.name); // 自定义属性. (程序员自己添加的属性)
console.debug(u.constructor);// 原型对象属性属性.
console.debug(u.hasOwnProperty);// 原型对象属性属性.
console.dir(u);
10.3. 对象属性访问过程
对象访问属性时首先会在对象自定义属性部分查找,如果自定义属性部分存在那么就使用;如果没有找到,那么就会到这个对象的原型部分(__proto__对象)查找,如果能找到就使用,如果没有找到,那么就会在这个对象的原型部分的原型部分查找对应的属性;
总结:对象访问属性,先在自定义部分查找,如果没有找到,就会去在原型上面查找;如果还没有原型对象的原型上面找,一直找到Object对象为止
10.4. 原型共享
同一类型的对象实例(构造函数相同),共享同一个原型对象。
10.5. 原型使用
JS对象属性访问过程为:先从对象自定义区域查找属性,如果有就使用,如果没有就到对象的原型区域中进行查找,并且原型区域可被多个对象共享使用,所以我们可以往原型对象上面添加属性或方法, 就相当于往对象上面添加了属性或方法。
/*
相同类型的对象,共享一个原型,我们往这个原型上面添加成员,相当于同类型对象添加成员.
*/
function User(name){
this.name = name;
}
//获取原型对象:"构造函数.prototype"
//原型对象只适合放公共的属性,如果每一个对象中属性值都不一样,那么没必要使用原型.
User.prototype.aaa = "呵呵";
User.prototype.getName = function(){
return this.name;
}
var u1 = new User("张三");
u1.aaa="哈哈"; //添加到u1自定义属性区域,并没有修改原型对象中aaa.
console.debug(u1.aaa);
var u2 = new User("李四");
console.debug(u2.aaa);
10.5.1. 笔试题:
/**
var a = 5;
var b = a.add(2);
console.debug(b);// b = 7
**/
//a 是 number类型,但是我们使用的时候可以把当成Number.
Number.prototype.add = function(num){
return num + this;
};
var a = 5;
var b = a.add(2);
console.debug(b);// b = 7
11.1. 重点
11.2. 难点
原文:https://www.cnblogs.com/Src-z/p/11218801.html