JavaScript 基础——快速上手
一、JavaScript简介
1、什么是JavaScript?
JavaScript是运行在浏览器上的脚本语言。简称JS。 JavaScript是网景公司(NetScape)的 布兰登·艾奇 开发的,最初叫做LiveScript。LiveScript的出现让浏览器更加生动,使得页面更具有交互性。 JavaScript(简称“JS”) 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。虽然它是作为开发Web页面的脚本语言而出名的,但是它也被用到了很多非浏览器环境中,JavaScript 基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式和声明式(如函数式编程)风格。
JavaScript在1995年由Netscape公司的Brendan Eich,在网景导航者浏览器上首次设计实现而成。因为Netscape与Sun合作,Netscape管理层希望它外观看起来像Java,因此取名为JavaScript。但实际上它的语法风格与Self及Scheme较为接近。
JavaScript和java没有任何关系,只是语法类似。JavaScript运行在浏览器中,代码由浏览器解释后执行。而Java运行在JVM中。
JavaScript的“目标程序”以普通文本形式保存,这种语言都叫做"脚本语言“。
Java的目标程序已.class形式存在,不能使用文本编辑器打开,不是脚本语言。
1998年网景公司由“美国在线”公司收购。
王景公司最著名的就是“领航者浏览器”:Navigator浏览器。 LiveScript的出现,最初的时候是为Navigator浏览器量身定制一门语言,不支持其他浏览器。
微软一看不行,研发了只支持IE浏览器的脚本语言。JScript。 在两者语言共存的时代,程序员需要写两套程序。这时一个叫做ECMA组织(欧洲计算机协会)根据JavaScript制定了ECMA-262标准,叫做ECMA-Script.
JavaScript是一种属于网络的脚本语言,已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的。
2、JavaScript构成
-
核心(ECMAScript)
-
文档对象模型(DOM)--document Object Module
-
浏览器对象模型(BOM)--Browser Object Module
ECMAScript:是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)通过ECMA-262标准化的脚本程序设计语言。这种语言在万维网上应用广泛,它往往被称为JavaScript或JScript,但实际上后两者是ECMA-262标准的实现和扩展
BOM: Browse Object Model,提供与浏览器交互的方法和接口
DOM: Document Object Model,提供访问和操作网页内容的方法和接口
3、 JavaScript 使用
在Web应用程序中,JavaScript是HTML文档的一部分,它是依托 HTML 而存在的。也就是说,必须把脚本的代码放在HTML文档中,否则它无法运行。JavaScript 程序可以用任何文本编辑器来编写。
1. 行级
给标签设置对应的属性,属性值是要执行的JavaScript代码。
<a href="javaScript:alert('你已经领取过了')">领取奖品</a>
<input type="button" value="点击有惊喜" onclick="alert('哈哈哈哈')">
2. 嵌入
使用script标签,标签需要闭合,标签内容是要执行的JavaScript代码,格式如下:
<script>
JavaScript 语言代码;
</script>
注:
① 可以将JavaScript代码嵌入到head中或body中的任何地方。
② 含在<script>元素内部的JavaScript代码将被从上至下依次解释。
3. 引入
使用script标签,标签需要闭合,设置属性src,src的值是js文件路径,如:./js/my.js。
<script src="./js/my.js"></script>
<script src="./js/my.js"/>
注:
① 嵌入和导入的数量不受限制;
② 使用script 标签引入外部js文件时(标明src属性,不管有没有赋值),标签内容部分再填写js语句是不能执行的;
③ js代码直接写在一个独立的文件里面,该文件就是js文件,后缀是.js
二、基础语法
1、语法规范
-
区分大小写
-
JavaScript区分大小写,包括关键字、变量、函数名、所有标识符;
-
querySelector的S是大写,你写成小写就会报错;
-
alert()全部是小写,你写一个大写字母就会提示你该函数不存在;
-
myname、myName、mynamE、MyName他们真不是一个东西;
-
-
注释
JavaScript支持两种注释方式;
单行注释 //这是注释内容 /* * 这是一个多行 * (块级)注释 */
-
虽然上面注释中的第二和第三行都以一个星号开头,但这不是必需的。之所以添加那两个星号,纯粹是为了提高注释的可读性(这种格式在企业级应用中用得比较多)。
-
注释部分不会执行,合理的注释能显著提高代码的可读性;
-
可以通过浏览器源文件看到注释内容,所以什么该注释什么不该注释要注意;
-
-
语句
ECMAScript 中的语句以一个分号结尾;如果省略分号,则由解析器确定语句的结尾,如下例所示:
var sum = a + b // 即使没有分号也是有效的语句——不推荐 var sum = a - b; // 有效的语句——推荐
虽然语句结尾的分号不是必需的,换行也可以表示一个语句结束,但我们建议任何时候都不要省略它。这样可以避免程序员犯一些低级错误,当然大佬也是可以忽略的,像我们这种小白还是好好写吧!
可以使用 C 风格的语法把多条语句组合到一个代码块中,即代码块以左花括号({)开头,以右花括号(})结尾:
if (test) { test = false; alert(test); }
虽然条件控制语句(如 if 语句)只在执行多条语句的情况下才要求使用代码块,但最佳实践是始终在控制语句中使用代码块——即使代码块中只有一条语句,例如:
if (test) alert(test); // 有效但容易出错,不要使用 if (test) { // 推荐使用 alert(test); }
在控制语句中使用代码块可以让编码意图更加清晰,而且也能降低修改代码时出错的几率。
-
标识符:所谓标识符,就是指变量、函数、属性、参数的名字,或者用做某些循环语句中的跳转位置的标记。
有以下注意事项:
-
只能由数字、字母、下划线和美元符号($)组成;
-
合法的标识符:myname、_age、$classname、abc、hqyj_h5;
-
不合法的标识符:5myname;
-
-
不能以数字开头;
-
不能是保留字和关键字;(下面会有介绍)
-
大小写敏感 age 、Age 这是两个完全不同的变量;
-
见名知意(尽量使用英文全称),例如年龄:age 而不是a阿b的;
-
单词个数超过两个之后;
-
驼峰式命名 className(用的比较多);
-
下划线命名 class_name;
-
-
2、关键字和保留字
ECMA-262 描述了一组具有特定用途的关键字,这些关键字可用于表示控制语句的开始或结束,或者用于执行特定操作等。按照规则,关键字也是语言保留的,不能用作标识符。以下就是 ECMAScript的全部关键字(带*号上标的是第 5 版新增的关键字):
ECMA-262 还描述了另外一组不能用作标识符的保留字。尽管保留字在这门语言中还没有任何特定的用途,但它们有可能在将来被用作关键字。以下是 ECMA-262 第 3 版定义的全部保留字:
3、变量
当程序需要将值保存起来以备将来使用时,便将其赋值给一个变量。变量(variable)是一个用于保存值的占位符,可以通过变量名称来获得对值的引用。
变量在JavaScript中就是用一个变量名表示,变量名是大小写英文、数字、$和_的组合,且不能用数字开头。变量名也不能是JavaScript的关键字,如if、while等。申明一个变量用var语句,比如:
var a; // 申明了变量a,此时a的值为undefined
var $b = 1; // 申明了变量$b,同时给$b赋值,此时$b的值为1
var s_007 = '007'; // s_007是一个字符串
var Answer = true; // Answer是一个布尔值true
var t = null; // t的值是null
在JavaScript中,使用赋值符号 = 对变量进行赋值。可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,但是要注意只能用var申明一次,例如:
var a = 123; // a的值是整数123
a = 'ABC'; // a变为字符串
4、 var声明
-
有var,系统就会在当前作用域的第一行代码隐式的声明一个变量(变量提升);
-
无var,系统帮你创建一个(全局)变量(运行到这里的时候)。
var abc = 'Hello, world';
abcd = "abcd";
-
严格模式下,使用没有var声明的变量会报错。
三、JavaScript数据类型
JavaScript的数据类型分类:
-
基本数据类型:Number、String、Boolean
-
特殊数据类型:NULL、Undefined、NaN
-
引用数据类型:数组、对象、函数等
1、typeof 操作符
typeof 就是负责鉴定数据类型的操作符。
对一个值使用 typeof 操作符可能返回下列某个字符串:
-
"undefined"——如果这个值未定义;
-
"boolean"——如果这个值是布尔值;
-
"string"——如果这个值是字符串;
-
"number"——如果这个值是数值;
-
"object"——如果这个值是对象或 null;
-
"function"——如果这个值是函数。
面试题--typeof 返回值
//返回值类型
console.log(typeof typeof 222); //string
typeof本身是字符串型,这里是一个坑要注意不要跳进去~
2、 Undefined类型
-
Undefined 类型只有一个值,即特殊的 undefined。
-
在使用 var 声明变量但未对其没有赋值时,这个变量的值就是 undefined
来个例子理解吧:
var message;
alert(message == undefined); //true
这个例子只声明了变量 message,但未对其进行赋值。比较这个变量与 undefined 字面量,结果表明它们是相等的。
3 、Null类型
-
null类型是第二个只有一个值的数据类型,这个特殊的值是 null。
-
实际上,ECMA-262 规定对它们的相等性测试要返回 true:
alert(null == undefined); //true,仅做判断不做字符串连接时
这里,位于 null 和 undefined 之间的相等操作符(==)总是返回 true。
null和undefined区别:
null
-
用来描述空值;
-
typeof null:返回的是字符串object
undefined
-
undefined表明只声明了变量没有赋值;
-
如果函数没有返回值,则返回undefined;
-
typeof undefined:返回的是字符串undefined;
-
==认为NULL和undefined是相等的;===则返回false;
4 、Boolean类型
Boolean 类型是 ECMAScript 中使用得最多的一种类型,该类型只有两个字面值: true 和 false。Boolean 类型的字面值 true 和 false 是区分大小写的。
5 、Number类型
用来表示整数和浮点数值
6、 String类型
字符串可以由双引号(")或单引号(')表示,因此下面两种字符串的写法都是有效的:
var firstColor = "pink";
var lastColor = 'blue';
字符串的特点
ECMAScript 中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量。
7、Object类型
ECMAScript 中的对象其实就是一组数据和功能的集合。对象可以通过执行 new 操作符后跟要创建的对象类型的名称来创建。
也就是说 对象=属性+方法
如下所示:
var o = new Object;
//var o={}
//为实例添加属性并赋值
o.name = "张三";
o.age = 24;
var o={
name:"张三",
age:24
}
也可使用大括号定义对象:
var person = {
name:'张三',
age:24,
say:function(){
console.log('大家好,我叫张三');
}
}
-
通过点(.)访问对象的属性:person.name;
-
通过点(.)访问对象的方法:person.say();
四、操作符
-
A&&B A为False时,执行A,B不运行; 反之执行B。
-
A||B A为True时,执行A,B不运行; 反之执行B;
在开发中优化代码最常用。
-
运算符:面试题:var f1=new new Fn.rank( )( )
-
开关思想:把一个变量中保存一个布尔值,然后再业务执行时,修改这个变量的值,为取反,然后通过变量的值执行分支业务。
-
排他思想:先清除所有的效果,然后赋予自己这个效果。
-
== 双等号 :“100”==100 值相等 但是类型不同 。引用数据比较时看内存空间,数值一样不一定相等。
难点:笔试题中喜欢考 == 的比较表(背它)
var arr=[] var b='' console.log(arr==b)//True //因为转换成了字符串,所以相等 var arr=[] //这是一个内存空间 var arr2=[[]] //这是内存空间 console.log(arr==arr2) //false
-
=== 三等号 :值和类型都要相等。
-
in运算符:检查右侧对象里面是否拥有左侧属性名,如果有返回true;反之,返回false。
实例代码:
var a = {x:1, y:2, z:''}; console.log(a); console.log('x' in a); console.log('z1' in a); console.log('toString' in a);
-
对象在js中是一种键值对的集合:key:value
-
逗号操作符多用于声明多个变量;但除此之外,逗号操作符还可以用于赋值。在用于赋值时,逗号操作符总会返回表达式中的最后一项,如下面的例子所示:
var num = (5, 1, 4, 8, 0); // num 的值为 0
-
eval() 函数会将传入的字符串当做 JavaScript 代码进行执行。
-
eval()
是全局对象的一个函数属性。 -
eval()
的参数是一个字符串。 -
如果
eval()
的参数不是字符串,eval()
会将参数原封不动地返回。
看一下例子:
console.log(eval('2 + 2')); // expected output: 4 console.log(eval(new String('2 + 2'))); // expected output: 2 + 2 console.log(eval('2 + 2') === eval('4')); // expected output: true console.log(eval('2 + 2') === eval(new String('2 + 2'))); // expected output: false
-
五、语句
1、定义:
表达式-----最简单的语句,
单语句:只有一条语句,每一个单语句结尾都要加分号;
复合语句:多条单语句组成 ; 语句组成程序。
空语句:啥都不写 ;
2、if语句:
js的执行引擎:如果执行体只有一条语句,可以省略执行体。
if-else if -else 语句 不是js的标准语法,是程序员利用js引擎的纠错功能实现的。
var a = 20;
if (a < 18) {
alert('未成年');
} else if (a > 22) {
alert('可以喝酒结婚')
} else {
alert('可以喝酒');
}
3、switch语句
switch 语句用于基于不同的条件来执行不同的动作。
使用 switch 语句来选择要执行的多个代码块之一。
语法如下:
switch(n) {
case 10: 执行代码块 1
break;
case 20: 执行代码块 2
break;
default: 与 case 1 和 case 2 不同时执行的代码
}
工作原理:首先设置表达式 n(通常是一个变量)。随后表达式的值会与结构中的每个 case 的值做比较。如果存在匹配,则与该 case 关联的代码块会被执行。请使用 break 来阻止代码自动地向下一个 case 运行。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>switch语法</title>
</head>
<body>
<p>点击下面的按钮来显示今天是周几:</p>
<button onclick="myFunction()">点击这里</button>
<p id="demo"></p>
<script>
function myFunction(){
var x;
var d=new Date().getDay();
switch (d){
case 0:x="今天是星期日";
break;
case 1:x="今天是星期一";
break;
case 2:x="今天是星期二";
break;
case 3:x="今天是星期三";
break;
case 4:x="今天是星期四";
break;
case 5:x="今天是星期五";
break;
case 6:x="今天是星期六";
break;
}
document.querySelector("demo").innerHTML=x;
}
</script>
</body>
</html>
·使用 default 关键词来规定匹配不存在时做的事情
switch 和 if 语句区别:
switch 更具有业务性
if语句 更具有逻辑性
4、 for语句(重要)
循环可以将代码块执行指定的次数。
如果希望一遍又一遍地运行相同的代码,并且每次的值都不同,那么使用循环是很方便的。
我们可以这样输出数组的值:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>for循环</title>
</head>
<body>
<script>
cars=["BMW","Volvo","Saab","Ford"];
for (var i=0;i<cars.length;i++){
document.write(cars[i] + "<br>");
}
console.log(i)
</script>
</body>
</html>
不同类型的循环
JavaScript 支持不同类型的循环:
-
for - 循环代码块一定的次数
-
for/in - 循环遍历对象的属性
-
while - 当指定的条件为 true 时循环指定的代码块
-
do/while - 同样当指定的条件为 true 时循环指定的代码块
for循环
for 循环是在希望创建循环时常会用到的工具。
语法如下:
for (语句 1; 语句 2; 语句 3)
{
被执行的代码块
}
for (语句 1; 语句 2;)
{
被执行的代码块;
语句 3;
}
-
语句 1 (代码块)循环开始前执行 starts.
-
语句 2 定义运行循环(代码块)的条件
-
语句 3 在每次循环(代码块)已被执行之后执行
考点:
//分析下面的结果 ?
//第一题
var i = 0;
for (; i++, i < 5;) {
console.log(i);
} //1 2 3 4
//第二题:闭包的作用域
var arr = [];
for (var i = 0; i < 4; i++) {
arr[i] = function () {
console.log(i)
};
}
arr[0]() //结果:4
arr[1]() //结果:4
/* 原因:
var arr=[]{
var i=0; //变成1,2,3
if(i<4){
arr[0] = function() {console.log(i)}
//不取值 函数没有调用
i=i+1;
if(1<4){
arr[1] = function() {console.log(i)}
i=i+1;
...
if(4<4){
} else{跳出循环}
}
}
}
最后执行 arr[0]() // 其实就是i在运行过程中一直在变化 最后加到了4
*/
for (var j = 0; j < 4; j++) {
arr[j];
}
//第三题
for (var i = 0, j = 6; i < 4, j > 0; i++, j--) {
console.log(i);
} //考点:由j>0控制
//结果 j:6 5 4 3 2 1 i输出:0 1 2 3 4 5
//for中的业务条件筛选
var arr = [{
age: 21,
name: 'karen',
rank: 580
},
{
age: 10,
name: 'jack',
rank: 380
},
{
age: 12,
name: 'marry',
rank: 540
},
{
age: 23,
name: 'rose',
rank: 880
}
]
/* //1.打印名字
for (var i = 0; i < arr.length; i++) {
console.log(arr[i].name);
} */
//2.打印大于18岁的名字
for (var i = 0; i < arr.length; i++) {
if (arr[i].age > 18) {
console.log(arr[i].name);
}
}
//3.打印年龄大于18 rank 大于480 的名字
for (var i = 0; i < arr.length; i++) {
if (arr[i].age > 18 && arr[i].rank > 480) {
console.log(arr[i].name);
}
}
//4.打印年龄小于18 rank大于400的对象的名字 拼接一个字符串“少年班” 大于18 且rank大于480 的普通班 其余的啥也不是
for (var i = 0; i < arr.length; i++) {
if (arr[i].age < 18 && arr[i].rank > 480) {
console.log(arr[i].name + '少年班');
} else if (arr[i].age >= 18 && arr[i].rank > 480) {
console.log(arr[i].name + '普通班');
} else {
console.log(arr[i].name + '啥也不是');
}
}
for循环嵌套思想:
-
不要管内部外部for 的执行问题,重点关注每一个for都是遍历自己的数组;
-
for 内部有条件语句和数据处理得到的数组,然后用for遍历
-
for大括号会执行数组的元素个数这么多次,每次执行时 i 就是元素的下标。
5、while 语句
-
语法
while (A) { 业务需要执行的代码 } //A判定为真,执行业务 循环 //A判定为假,直接结束while语句 var i=0 for(;i<len;){ //需要执行的代码 i++; }
-
怎样判断选择while和for 循环?
-
while循环:如果有一个业务需要重复执行,但是总有一次执行会让他停下来不再执行,不知道循环次数。
-
for 循环: 一个业务需要重复执行,但是是已知次数。
-
6、continue和break 语句
-
break 语句用于跳出循环。
-
continue 用于跳过循环中的一个迭代,继续执行下一个迭代(如果有的话)。
break 语句举例如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <p>点击按钮,测试带有 break 语句的循环。</p> <button onclick="myFunction()">点击这里</button> <p id="demo"></p> <script> function myFunction(){ var x="",i=0; for (i=0;i<10;i++){ if (i==3){ break; } x=x + "该数字为 " + i + "<br>"; } document.getElementById("demo").innerHTML=x; } </script> </body> </html>
continue 语句举例如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <p>点击下面的按钮来执行循环,该循环会跳过 i=3 的步进。</p> <button onclick="myFunction()">点击这里</button> <p id="demo"></p> <script> function myFunction(){ var x="",i=0; for (i=0;i<10;i++){ if (i==3){ continue; } x=x + "该数字为 " + i + "<br>";//9行 } document.getElementById("demo").innerHTML=x; } </script> </body> </html>
7、 label 语句
标签语句,在语句之前加上冒号:可标记 JavaScript 语句。
语法如下:
label: statements
break 和 continue可以使用标签语句。
var a = 0;
forhere:
for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
if(j == 5){
break forhere;
//这里终止的是外面的for循环
//体会continue、break后面加和不加语句标签的区别;
}
a++;
}
}
console.log(a);
并且:
continue 语句(带有或不带标签引用)只能用在循环中。
break 语句(不带标签引用),只能用在循环或 switch 中。
通过标签引用,break 语句可用于跳出任何 JavaScript 代码块:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script>
cars=["BMW","Volvo","Saab","Ford"];
list:{
document.write(cars[0] + "<br>");
document.write(cars[1] + "<br>");
document.write(cars[2] + "<br>");
break list;
document.write(cars[3] + "<br>");
document.write(cars[4] + "<br>");
document.write(cars[5] + "<br>");
}
</script>
</body>
</html>
8、throw抛出异常
1.立即停止正在执行的程序,跳转至就近的逻辑异常处理程序。
例子:
function factorial (n) {
if(isNaN(n)) throw new Error('请输入数字,HOHO');
if(n == 1) return 1;
return n*factorial(n-1);//递归
}
var n = factorial(3);//3*factorial(2)--3*2*factorial(1)--3*2*1
console.log(n);//6
var n = factorial('a05');
console.log(n);
var n = factorial(5);
console.log(n);
2.throw抛出异常该异常可以是 JavaScript 字符串、数字、逻辑值或对象。
3.js语言,是脚本语言,当运行过程终于到了错误就停止运行后面的代码。
9、try-catch-finally语句
-
try-catch-finally是JavaScript的异常处理机制。
-
语法
try{ //我们自认为没有错误的 处理业务的代码 } catch(e){ //上面的业务处理代码报错了,这里才会执行 //console.log(e); } finally{ //这里总是会执行的,理解为领导总结发言 } //语句 不会影响到后面代码的执行。
异常对象e里面有两个属性name和message,分别代表错误类型和错误描述信息。
-
例子
try { console.log(1); throw new Error('出错了'); console.log(2); //不会打印2 } catch (e) { console.log(e.message); //打印throw里面的内容,里面写其他的字符串也行 } finally { console.log(4); }
10、with语句(了解)
例子:
<script>
var a = 20;
var b = 10;
console.log(window.b); //window 全局变量 可省略
var obj = {
age: 20,
name: "karen"
};
with(obj) {
console.log(name);
}
/* //我们平常使用的这里代码有一个隐式操作 with(window){
} */
console.log(age); //报错
</script>
不建议使用,语法有性能问题,es6 解决了这个问题
新技术:解构赋值
var {age,name}=obj;
console.log(age)
六、对象
JavaScript 对象是拥有属性和方法的数据。
真实生活中的对象、属性和方法
真实生活中,一辆汽车是一个对象。
对象有它的属性,如重量和颜色等,方法有启动停止等:
所有汽车都有这些属性,但是每款车的属性都不尽相同。
所有汽车都拥有这些方法,但是它们被执行的时间都不尽相同。
JavaScript的对象
在 JavaScript中,几乎所有的事物都是对象。在 JavaScript 中,对象是非常重要的,当你理解了对象,就可以了解 JavaScript 。
已经学习了 JavaScript 变量的赋值。
var car = "Fiat";
对象也是一个变量,但对象可以包含多个值(多个变量)。
var car = {
type:"Fiat",
model:500,
color:"white"
};
在以上实例中,3 个值 ("Fiat", 500, "white") 赋予变量 car,3 个变量 (type, model, color) 赋予变量 car。
1 对象基础
1.1 对象创建
1.对象字面量
var person1 = {
name: "bai",
age : 29,
job: "Software Engineer",
sayName: function(){
alert(this.name);
}
};
对象字面量可以用来创建单个对象,但如果要创建多个对象,会产生大量的重复代码。
2. 工厂模式
为了解决上述问题,人们开始使用工厂模式。该模式抽象了创建具体对象的过程,用函数来封装以特定接口创建对象的细节
function createPerson(name,age,job){
var o = new Object();//var o={}
o.name = name;
o.age = age;
o.job = job;
o.sayname = function(){
alert(this.name);
}
return o;
}
var person1 = createPerson('bai',29,'software Engineer');
var person2 = createPerson('hu',25,'software Engineer');
3. 构造函数模式
可以通过创建自定义的构造函数,来定义自定义对象类型的属性和方法。创建自定义的构造函数意味着可以将它的实例标识为一种特定的类型,而这正是构造函数模式胜过工厂模式的地方。该模式没有显式地创建对象,直接将属性和方法赋给了this对象,且没有return语句
function Person(name,age,job){
//var this={}
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
}
var person1 = new Person("bai",29,"software Engineer");
var person2 = new Person("hu",25,"software Engineer");
//具有相同作用的sayName()方法在person1和person2这两个实例中却占用了不同的内存空间
console.log(person1.sayName == person2.sayName);//false
使用构造函数的主要问题是每个方法都要在每个实例上重新创建一遍。
4. new创建
new后面跟一个函数表示创建对象;
var obj1 = new Object();
console.log(obj1);
var obj2 = new Date();
console.log(obj2);
var obj3 = new Array();
console.log(obj3);
这里的函数是构造函数(constructor)。
5. Object.create()创建
Object.create()的参数只能是对象或null;
用于创建一个新对象,参数是这个对象的原型(后续章节会详细介绍原型的概念)。
var b = Object.create(new Array(14,5,6,2,3,7));
console.log(b.length);
var nu = Object.create(new String('null'));
console.log(nu[2]);
var nu = Object.create(null);
console.log(nu[2]);
2 对象方法
1. valueOf()
valueOf()方法返回当前对象原始值
var o = new Object();
o.valueOf() === o //true
console.log(new Date().valueOf())//得到XX ms(毫秒)
object 引用是任何内部 JavaScript 对象,将通过不同的方式为每个内部 JavaScript 对象定义 valueOf 方法。
2. toString()
toString()方法返回当前对象对应的字符串形式
var o1 = new Object();
o1.toString()
var o2 = {a:1};
o2.toString()
//函数调用该方法返回的是函数本身的代码
function hq (argument) {
// body...
}
console.log(hq.toString());
var a = [1,2,3];
console.log(a.toString());
console.log(new Date().toString())
toString 方法是一个所有内置的 JavaScript 对象的成员。 它的行为取决于对象的类型:
Object | 行为 |
---|---|
数组 | 将Array的元素转换为字符串,结果字符串被连接起来,用逗号分隔 |
布尔值 | 如果布尔值为true,则返回"true",否则返回"false" |
日期 | 返回日期的文本表示形式 |
错误 | 返回一个包含相关错误信息的字符串 |
函数 | 返回如下格式的字符串,其中functionName是函数的名称 function functionName() { [native code] } |
Number | 返回数字的文字表示形式 |
字符串 | 返回String对象的值 |
默认{} | 返回"[object Object]" |
附注:valueOf偏向于运算,toString偏向于显示。
1、 在进行强转字符串类型时将优先调用toString方法,强转为数字时优先调用valueOf。
2、 在有运算操作符的情况下,valueOf的优先级高于toString。
七、函数
函数对任何一门语言来说都是核心的概念。通过函数可以封装任意多条语句,而且可以在任何地方、任何时候调用执行。在javascript里,函数即对象,程序可以随意操控它们。函数可以嵌套在其他函数中定义,这样它们就可以访问它们被定义时所处的作用域中的任何变量,它给javascript带来了非常强劲的编程能力。
1 函数概述
– 一处定义,处处调用;
– 如果把函数作为一个对象的属性,则称为方法;
– 每次调用函数会产生一个this:谁调用这个函数或者方法,this就指向谁;
– 函数就是对象,可以给他设置属性或方法;
函数定义
总共有三种函数定义的方式:函数声明语句、函数表达式、内置构造函数。
-
函数声明语句
function functionName(parameters) { //执行的代码 }
函数声明后不会立即执行,会在我们需要的时候调用到。
看一些权威函数:
function distance (x1, y1, x2, y2) { var x = x2 - x1; var y = y2 - y1; return Math.sqrt(x*x + y*y).toFixed(2); } console.log( distance(3, 5, 8, 20) );
小练习:定义一个求阶乘的函数。
function fn2(n) { var s = n; var result = 1; for (var n; n >= 1; n--) { result *= n; } console.log(s + '的阶乘等于' + result); } fn2(12);
-
函数表达式
var functionName = function (parameters) { //执行的代码 }; //函数以分号结尾,因为它实际上是一个执行语句
以上函数实际上是一个 匿名函数 (函数没有名称),函数存储于变量中,故通常不加函数名。
当写递归函数时,也可加上函数名。
定义一个表达式函数:
var square = function factorial(h) { if(h===1) {return 1;} else {return h*factorial(h-1);} } console.log(square(3));
-
Function内置构造函数
在以上实例中,我们了解到函数通过关键字 function 定义。
函数同样可以通过内置的 JavaScript 函数构造器(Function())定义。
var functionName = new Function("parameters","执行的代码") //注意引号不可省
这种方式不推荐,无法写递归。
用Function()构造函数创建一个函数时并不遵循典型的作用域,它一直把它当作是顶级函数来执行。所以,在 JavaScript 中,很多时候,你需要避免使用 new 关键字。
var y = "global"; function constructFunction() { var y = "local"; function test(){}; return new Function("return y"); // 无法获取局部变量,作用域始终是全局作用域 } alert( constructFunction()() );
补充:函数可以嵌套在其他函数里面,也就是在函数里面可以定义函数(感觉半句废话)
function distance (x1, y1, x2, y2) {
var n = 10;
function square(h) { console.log(n);return h*h;}
return Math.sqrt(square(x2-x1) + square(y2-y1)).toFixed(2);
}//
被嵌套的函数可以访问嵌套他们的函数的变量或参数。
2 函数调用
javascript一共有4种调用模式:函数调用模式、方法调用模式、构造器调用模式和间接调用模式。
每种方式的不同在于 this 的初始化。
-
函数调用方式
var myfunc = function(a,b){ console.log(this); return a+b; } alert( myfunc(3,4) );
函数调用模式中:
a, this是指向Window的
b, 返回值是由return语句决定的,如果没有return则表示没有返回值
-
方法调用模式
先定义一个对象,然后在对象的属性中定义方法,通过myobject.property来执行方法。
var name = "james"; var obj = { name : "wade", fn1 : function () { console.log(this.name); } }; obj.fn1(); //wade
方法调用模式中:
a, this 是指向调用该方法的对象
b, 返回值还是由return语句决定,如果没有return表示没有返回值
-
构造器调用模式
如果函数或者方法调用之前带有关键字new,它就当成构造函数调用。
function Fn () { this.name = "james"; this.age = 32; console.log(this); }; var fn1 = new Fn(); //Fn整个对象 console.log(fn1); //Fn整个对象
通过上面的代码结果分析,会得到以下结论(构造函数调用模式中):
a, this是指向构造函数的实例
b, 如果没有添加返回值的话,默认的返回值是this
但是如果手动添加返回值之后呢?
function Fn1 () { this.name = "james"; return "wade" ; }; var fn1 = new Fn1(); console.log(fn1); console.log(fn1.name); function Fn2 () { this.name = "james"; return [1,2,3]; }; var fn2 = new Fn2(); console.log(fn2); console.log(fn2.name);
而通过上面的代码结果分析,优化上面的结论:
a, this是指向构造函数的实例
b, 如果没有添加返回值的话,默认的返回值是this
c, 如果有返回值,且返回值是简单数据类型(Number,String,Boolean··)的话,最后仍回返回this
d, 如果有返回值,且返回值是复杂数据类型(对象)的话,最终返回该对象,所以上面的fn2是指向数组,所以fn2.name为undefined
-
间接调用模式
也称之为“apply、call调用模式” 或 “上下文调用模式”。
var myobject={}; var sum = function(a,b){ console.log(this); return a+b; }; var sum2 = sum.call(myobject,10,30); alert(sum2);
由之前所学,this指向由传入的第一个参数决定。
再看看,下面函数调用中this指向如何呢?
function f1(){ console.log(this); } f1.call(null); f1.call(undefined); f1.call(123); f1.call("abc"); f1.call(true); f1.call([1,2,3]);
通过上面的代码结果分析,得出以下结论(上下文调用模式中):
a, 传递的参数不同,this的指向不同,this会指向传入参数的数据类型
b, 返回值是由return决定,如果没有return表示没有返回值。
前端小白,有错误之处还请指正~~~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具