行内引入方式必须结合元素的事件来使用,但是内部js和外部js可以不结合事件<button οnclick="alert('点击了我'))">点击我</button
在head或body中,定义script标签,然后在script标签里面写js代码
<script>
alert("这是js的内部引入");
</script>
定义外部js文件(.js结尾的文件)<script type="text/javascript" src="demo.js"></script>
注意:script标签要单独使用,要么引入外部js,要么定义内部js,不要混搭使用,就算在外部引入标签内编写代码也不会起作用。
字面量(Literals):有些书叫做“直接量”、“常量”;
通俗理解:字面量就认为是字面上的意思,所见即所得。计算机在遇到字面量时,立即知道数据类型是什么,数据的值是什么。
变量(Variables),相当于一个容器,内部可以放任何类型的数据,和高中代数学习x、y、z很像。它们不是字母,而是蕴含值的符号。它和字面量不同,字面量5就是数字5,字面量“你好”就是字符串“你好”。现在这个变量不一样了,你看见一个a,实际上不是字母a,而是蕴含着不同的值。
方式一: 使用 var 定义变量,可在定义的同时赋值 或 不赋值 。
方式二: 使用 let 定义变量,此方式可以用来声明块作用域的局部变量(block scope local variable) 。【例如 for 循环中定义的初始值】后面介绍他们区别
方式三:直接使用【变量名 = 值】的形式,这会定义一个全局变量,但在严格模式下会出现引用错误。【不建议使用】
声明:let 变量名;
赋值:变量 = 变量值;
声明:let a; //定义了一个a变量
赋值:a = 100; //给a变量赋值
声明并赋值: let a = 100;
通过“=”号给变量内部存储数据,专业叫法“变量赋值”。
你的电脑内存中,就会开辟一个空间,用来存放这个变量a,把右边的值,赋值给左边的变量名,let是声明变量的意思。
变量声明又叫做“变量定义”或“创建变量”。使用关键字var,后面定义变量的名字(名称自定义)。变量名定义需要遵循一个标识符命名规范。
let 这个过程可以叫做声明(declaration),也可以叫做定义(definition)
直接运行以下代码:console.log(a);
会提示报错,a is not defined
1、必须以字母、“_”或“$”符号开头,后面可以是数字、字母、下划线等
2、变量名不能包含空格或加减号或特殊符号
3、JavaScript变量名是严格区分大小写,例如A和a代表不同的变量
4、不能使用JavaScript中关键字和保留字
关键字:JavaScript中具备特殊意义的词,已经被JS占用,不能用来命名
break do instanceof typeof case else new var catch finally return void continue for switch while debugger* function this with default if throw delete in try
保留字:现在没有特殊功能,但是未来可能成为关键字
abstract enum int short boolean export interface static byte extends long super char final native class
synchronized float package throws const goto private transient debugger implements protected volatile double
import public
程序中的命名规范:一般使用驼峰命名法或其他(第一个单词首字母小写,后面每个单词首字母大写)
命名方案:
这是JavaScript特有的一个特点,其他编程语言没有。
JavaScript 变量的另一特别之处是,你可以引用稍后声明的变量,而不会引发异常。这一概念称为“变量声明提升(hoisting)”;JavaScript 变量感觉上是被“举起”或提升到了所有函数和语句之前。然而提升后的变量将返回 undefined 值,所以即使在使用或引用某个变量之后存在声明和初始化操作,仍将得到 undefined 值。
现在我们先去改变变量的值,然后声明变量,由于JS有一个机制,叫做“变量声明”提升,所以现在在程序执行前会已经看见这个程序有一行声明变量的代码,所以就会被提升到程序开头去运行。
首先举个栗子~
console.log(a);
上面会输出什么呢?
当然会报错,变量必须先声明在使用
那我们看下面一个
console.log(a);
var a = 2;
则就会输出 undefined(已声明未定义值)
当你看到 var a = 2;时,可能会认为这只是一个简单的声明语句。但 JavaScript 实际上会将其看成两个声明: var a; 和 a = 2;。第一个定义声明是在编译阶段进行的,第二个赋值声明会被留在原地等待执行阶段。
因此上面的代码会以如下的形式进行处理:
var a;
console.log(a);
a = 2;
注:无论作用域中的声明出现在什么地方,都将在代码本身被执行前首先进行处理。可以将这个过程形象地想象成所有的声明(变量和函数)都会被“移动”到各自作用域的最前端,这个过程被称为 变量(函数)提升
常量的意思就是不可以改变的,一旦定义就不会被改变。
console.log('zhangshuai');
console.log('zhangshuai');
console.log('zhangshuai');
console.log('zhangshuai');
// 多次使用且不改变其值
var NAME = 'zhangshuai';
console.log(NAME);
console.log(NAME);
注意:在ES6之前并没有常量一说,通常使用名称大写 var NAME = ‘zhangshuai’来约定。
关键字为 const
语法: const PI = 1.1313131;
通常使用名称全大写的形式,其值不可改变,且必须在定义时赋值。
注: 使用 let 或 const 定义的变量,必须先声明后使用,并不会出现【变量提升】,如果在未定义前使用变量,则会出现【引用错误】。let不允许在相同作用域内,重复声明同一个变量,const0只能在声明时赋值,之后不能再重新赋值
数据:计算机看到的所有对象都是数据,数据分很多类,都会分类保存。
JavaScript中的值:无论是字面量还是变量,都有明确的类型。
js 中的六种数据类型
原始类型:① number;② string;③ boolean;④ null;⑤ undefined
对象类型:⑥ object(Function函数,Array数组,Date日期 等都是 object 类型)
Number 数字类型,不区分整数、浮点数、特殊值、进制
String 字符串类型,所有有引号的数据都是字符串类型
Boolean 布尔类型,仅有两个值true(真)和false(假)
undefined undefined类型,变量未定义时的值,这个自己是一种类型。
null Object类型,这个值自己是一种类型,null本身是个空对象。
js 类型检测:
用typeof这个关键字可以检测变量的值是什么类型
let a = 123456; //Number类型
let b = "你好"; //String类型
let c = true; //Boolean类型
let d = null; //null类型(空对象)
let e; //undefined类型
console.log(typeof a);
console.log(typeof b);
console.log(typeof c);
console.log(typeof(d));
console.log(typeof(e));
扩展:
[1,2] instanceof Array //返回true
new Object() instanceof Array //返回false
Object.prototype.toString.apply([]); //返回 "[object Array]"
Object.prototype.toString.apply(function(){}); //返回 "[object Function]"
Object.prototype.toString.apply(null); //返回 "[object Null]"
Object.prototype.toString.apply(undefined); //返回 "[object Undefined]"
隐式转换是自动转换的,为了避免我们在执行代码的时候,出现我们不知道的结果,需要自己来总结出隐式转换都有哪些,下面是我做出一部分总结希望对你有所帮助。
+
:会将字符当做字符处理拼接- * / %
:将字符当成数值处理;
console.log(2 + '1') // 21
console.log(2 - '1') // 1
console.log('2' - '2ac') // NaN 非法数值型
==
两边值类型不同的时候,要先进行类型转换,再比较。 (只要值相等即可为真)===
不做类型转换,类型不同的一定不等。(值和类型都相等才为真)
注意:以后尽可能只用三个等号’===’
console.log(100 == '100') //true
console.log(100 === '100')//false
规则:其他数据类型转布尔型
数值型:非0为true,0为false
字符型:非空为true,空为false
对象:除了null,所有对象为true
undefined,NaN,null:为fasle
string 转 number类型
parseInt() 转换为整数
parseInt()就是将一个String类型或浮点数转换为整数,不四舍五入,直接截取整数部分,如果这个String有乱七八糟的内容,直接截取前面数字部分。
let a = '123';
console.log(typeof a); //string
console.log(typeof parseInt(a)); //number
//下面的案例结果都是Number类型
console.log(parseInt('123')); //123
console.log(parseInt('123.6')); //123
console.log(parseInt('123块钱')); //123
console.log(parseInt('我有123块钱')); //NaN
parseFloat() 转换为浮点数
尽可能将一个字符串转换为浮点数,浮点数后面如果有其他内容,直接舍弃。
let a = '123.456.888';
let b = parseFloat(a);
console.log(a);
console.log(b);
console.log(typeof Number("123"));
console.log(Number("123px"));
console.log(Number(true));
console.log(Number(false));
console.log(Number(undefined));
console.log(Number(Infinity));
console.log(typeof String(123));
console.log(String("123px"));
console.log(String(true));
console.log(String(false));
console.log(String(1));
console.log(String(0));
console.log(String(undefined));
console.log(String(Infinity));
一:声明式函数(也叫命名函数,通俗叫有名称的函数)
语法 :
function getName(){
执行代码块;
return 返回值
}
注:函数可带参数 或 返回值,也可不带。若有参数,调用函数时则需要添加对应参数。若有返回值,则在调用函数时,应提供一个容器(如变量)接收返回值 。
// 函数声明 形参数
function getName(name){
return "welcome to:"+name;
}
// 函数调用
let a = getName("zhangshuai")
// 打印返回值
console.log(a); // zhangshuai
二:函数表达式(也叫匿名函数,通俗叫没有名称的函数)
语法:
let fun = function(){
执行代码块;
return 返回值
}
注:以上例子中,fun 即为 变量名称 ,也为函数名称,当使用 fun 相当于得到整个函数体,当使用 fun() 相当于调用此函数 。
let fun = function(){
console.log(111);
}
fun(); // 111
let bb = fun;
console.log(bb); // function fun()
三: 立即执行函数(也叫自调用函数,IIFE)
语法:
(function(){
console.log(123);
})()
四: 箭头函数表达式
普通函数function () {}
箭头函数()=>{}
当函数只有一个参数的时候()可以省略
当只有一个return的时候{}可以省略
箭头函数简化x => x * x;
注意:普通函数和箭头函数的this指向有很大区别,将在后面学习中总结介绍。
当函数执行完的时候,并不是所有时候都要把结果打印。我们期望函数给我一些反馈(比如计算的结果返回进行后续的运算),这个时候可以让函数返回一些东西。也就是返回值。函数通过return返回一个返回值
1.每一个函数都会有一个返回值,这个返回值可以通过关键字“return”进行设置
//声明一个带返回值的函数
function 函数名(形参1, 形参2, 形参3...) {
//函数体
return 返回值;
}
//可以通过变量来接收这个返回值
var 变量 = 函数名(实参1, 实参2, 实参3...)
2.若未显式地设置函数的返回值,那函数会默认返回一个undefined值
function fn(){}
fn() // undefined
3.但若手动地设置了函数的返回值(return)后,函数将返回开发者手动设置的那个值
function fn(){
return 666;
}
fn() // 666
4.在函数中,一旦执行完成“return”语句,那么整个函数就结束了,后续语句将不再执行;
function fn(a){
return a;
console.log('我不会执行')
}
console.log(fn(5)) // 5
5.就是“return”之后的值只能有一个。如果尝试返回多个值,那得到的结果始终是最后一个值
function fn(a,b){
return a,b;
}
console.log(fn(5,6)) // 5
6.如果真的需要函数返回多个值,那就只有将值组合成一个对象或数组进行返回
function fn(a,b){
return [a,b];
}
console.log(fn(5,6)) // (2) [5, 6]
7.实参的个数必须大于形参,为避免出错,我们可以给形参设置默认值
function fn(a=1,b=2,c=3){
console.log(a+b+c);
}
fn(2); // 2+2+3=7
8.函数中的 Rest 参数
function add(...arr){
// var result = 0;
// for(let i=0;i<arr.length;i++){
// result = result + arr[i];
// }
// return result;
return arr.reduce((p,c)=>p+c);
}
var r = add(6,9,3,2);
console.log(r); // 20
9.JavaScript函数的rest参数也可以与其他参数一起工作
function add(num1, num2, ...theArgs){
console.log(num1);
console.log(num2);
console.log(theArgs.length);
}
var r = add(6,9,3,2);
var t = add(7,56,9);
高阶函数在 JavaScript 中广泛使用。是对其他函数进行操作的函数,操作可以是将它们作为参数,或者是返回它们。 简单来说,高阶函数是一个接收函数作为参数或将函数作为输出返回的函数。
例如,Array.prototype.map,Array.prototype.filter 和 Array.prototype.reduce 是语言中内置的一些高阶函数。
function demo1(fn){
fn();
return function(){
console.log('返回的函数')
}
}
let demo2 = demo1(function(){
console.log('我是函数参数')
});
demo2();
(回调函数)
回调函数就是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。这个过程就叫做回调。
document.addEventListener('click',function(){
alert('单击我弹窗')
})
(偏函数)
偏函数是 JS 函数柯里化运算的一种特定应用场景。简单描述,就是把一个函数的某些参数先固化,也就是设置默认值,返回一个新的函数,在新函数中继续接收剩余参数,这样调用这个新函数会更简单。
let sum = function(a,b){
return function(c,d){
return a+b+c+d;
}
}
let f1 = sum(1,2); // 返回一个函数
console.log(f1(3,4)); // 10
假设我们有一个数字数组,我们想要创建一个新数组,其中包含第一个数组中每个值的两倍。 让我们看看如何使用和不使用高阶函数来解决问题。
不使用高阶函数
const arr1 = [1,2,3,4];
const arr2 = [];
for(let i = 0; i < arr1.length;i++){
arr2.push(arr1[i]*2)
}
使用高阶函数 map
const arr1 = [1,2,3,4,5,6];
const arr2 = arr1.map(function(item){
return item*2;
});
console.log(arr2);
使用箭头函数语法将更简短:
const arr1 = [1,2,3];
const arr2 = arr1.map(item=>item*2);
console.log(arr2);
(纯函数)在函数内部没有引用外部数据的函数
// 纯函数
function add(a,b){
return a+b;
}
add(2,3);
// 非纯函数
let c = 4;
function add(a,b){
return a+b+c;
}
add(2,3);
var a = 10;
foo();
function foo() {
console.log(a);
var a = 6;
}
这个例子最终的答案是 undefined
下面是这段代码实际会被 JavaScript 执行的样子:
function foo() {
var a;
console.log(a);
a = 6;
}
var a;
a = 10;
foo(); // undefined
函数声明和变量声明都会被提升。但是有一个需要注意的细节是函数会首先被提升,然后才是变量。
注: 函数提升,只有声明式(命名)函数能够提升,表达式(匿名)函数没有提升。
作业
// 行内引入
<button onclick="alert('提示')">按钮</button>
// 内部引入
<script>
console.log('内部引入');
</script>
// 外部引入
<script type="text/javascript" src="demo.js"></script>
// 变量声明并赋值
let myName = 'zhang';
const = MYNAME = 'zhang';
console.log(a,b)
// 普通函数
function fn(a,b){
console.log(a,b);
return a+b;
}
let a = fn(2,3);
console.log(a);
// 高阶函数 map
const arr1 = [1,2,3,4,5,6];
const arr2 = arr1.map(function(item){
return item*2;
});
console.log(arr2);
function fn(a,b){
return a,b;
}
console.log(fn(5,6)) // 5
function fn(a=1,b=2,c=3){
console.log(a+b+c);
}
fn(2); // 2+2+3=7
function add(num1, num2, ...theArgs){
console.log(num1);
console.log(num2);
console.log(theArgs.length);
}
var r = add(6,9,3,2);
var t = add(7,56,9);
// 普通函数
let sum1 = function(a,b){
return a+b;
}
// 箭头函数 箭头函数是用来简化匿名函数的
let sum2 = (a,b) => a+b;
console.log(sum2(5,6));
let tips = name => console.log('欢迎'+name+'同学!');
tips('小张');
(function(a,b){
console.log(a+b);
})(1,2);
// 主要用途:在ES5的时候,是没有块级作用域的。为了将内部声明的变量不泄露到全局作用域中,我们通常将代码跨用一个立即执行函数包裹起来。
if(true){
var a = 100;
}
console.log(a); // 100
(function(){
if(true){
var b = 100;
}})()
console.log(b); // b is not defined
今天很残酷,明天很残酷,后天很美好,但绝大多数人死在明天的晚上,见不了后天的太阳!
程序猿的路上,且行且坚持!