html中使用javascript

将js插入html主要是用<script>元素,这个元素有八个属性

  • async: 表示应该立即下载脚本,但是不阻止其它页面动作(如加载页面,加载其他脚本等),只对外部脚本有效.async标记的脚本之间没有前后顺序关系。
  • charset: 指定字符集,但是很少用
  • crossorigin: 配置相关请求的CORS(跨源资源共享)设置。crossorigin="anonymous"表示配置文件请求不必设置凭据标识,而use-credentials表示出站请求会包含凭据
  • defer: 表示文档解析和显示完成后再执行脚本也是可以的,即推迟执行。有时候会在DOMContentLoaded事件之前执行(此时已经解析完</html>了),并且推迟执行的脚本也会按顺序执行。但是都不是绝对的。
  • integrity: 允许比对接收到的资源和指定的加密签名来验证子资源完整性
  • src: 表示包含的外部文件地址
  • type: 这个值始终是”text/javascript”

使用script时,一般把<script>元素放在<head>标签内,但是他会在文档载入前解析,如果解析很慢就会感觉载入时间很长。

插入脚本的方式有:

  1. 直接在html中插入
    例如
    <script>
    function hello()
    {
    console.log("Hello");
    }
    </script>
    需要注意在代码块中不能使用</script>即使时在log中用引号包围也不行,想要使用必须是<\/script>
  2. 外部引入
    使用方法为<script src="example.js"></script>.解释外部script时和解释行内script一样,也会阻塞。
  3. 使用js语句加载
    let script = document.createElement('script');
    script.src = 'gibberish.js';
    document.head.appendChild(script);
    这种方式加载的script自带async属性。但是这种加载方式对浏览器预加载器是不可见的,这会严重影响它在资源队列中的优先级。如果想让预加载器知道这些动态请求文件的存在,可以显式声明。例如:<link rel="preload" href="gibberish.js">

语法

基础语法和c语言类似,并且变量命名添加了$.并且操作符语法和python类似

变量

var

变量和c语言有很大不同。在c语言中,变量有int,long,short,char等类型。但是在js中并不区分这些类型,而统一使用var代替,他和python一样都是弱类型语言。

例如:

var message = "hi";
message = 100;//合法,但不推荐

var表示的就是一个变量,它并不会随着赋值而将类型确定。

此外var声明时会自动提升到函数的顶部,例如:

function foo()
{
console.log(age);
var age = 26;
}
这个可以运行,他相当于
function foo()
{
var age;
console.log(age);
age = 26;
}

let

let和var都是声明变量,不同在于let只作用于某个块,而var作用于整个函数,例如:

if(true)
{
var name = 'a';
console.log(name);
}
console.log(name);//输出a

if(true)
{
let age = 26;
console.log(26);
}
console.log(age);//出错

也就是说,let与c语言中的局部变量类似。

此外let不允许在同一个块中出现两次声明,例如:

var name;
var name;//允许

let age;
let age;//出错
如果不在同一个作用域中就没有问题了

let age = 30;
console.log(age);
if(true)
{
let age = 26;
console.log(age);//26
}
console.log(age);//30

这里和c语言还有点不一样,外层变量可以传递到里层,而里层变量对外层没有任何影响

let age = 30;
console.log(age);//30
if(true)
{
age = 26;
console.log(age);//26
}
console.log(age);//30

此外,let和var声明的其实是相同类型的变量,只是作用域不同,因此这两个的变量名不能相同

var name;
let name;//错误

并且let声明的变量不会再作用域中提升,并且不能使用let进行全局声明

var name = 'a';
console.log(window.name);//'a'

let age = 26;
console.log(window.age);//undefined

条件声明

因为let作用于块作用域,所以无法检测前面是否使用了同名变量,但是由于var会自动提升变量,所以它可以在首部合并为一个声明,例如:

<script>
var name = 'a';
let age = 26;
</script>

<script>
var name = 'b';
let age = 20;//出错,前面已经声明过

let经常用于for循环中

在let出现之前,使用var进行循环变量定义有时候会出现问题

for(var i=0; i<5; i++)
{
setTimeout(()=>console.log(i), 0);
}

输出为5, 5, 5, 5, 5

为什么结果不是0, 1, 2, 3, 4呢?因为在退出循环时,i中保存的是5,在之后的执行中会一直输出5

for(let i=0; i<5; i++)
{
setTimeout(()=>console.log(i), 0);
}
输出0, 1, 2, 3, 4

这是因为js会为每次迭代生成一个新的let变量,这样就会输出期望的值了

const

const和let基本相同,但是它在声明时必须同时初始化变量,并且禁止修改const声明的变量,否则会报错。

但是const声明限制只适用于变量的引用。也就是说,如果修改一个对象内部变量,它是管不了的

const person = {};
person.name = 'a';//可以

数据类型

我们可以使用typeof操作符来查看数据类型,typeof会返回这些类型

  • undefined: 表示值未定义.也就是var或let声明但没有初始化时的值
  • boolean:
  • string: 可以通过num.tostring()转换为字符串.可以使用单引号(‘), 双引号(“),反引号(`)表示。其中反引号可以跨行定义字符串,跨行字符串会保留反引号内部的空格
  • number: 数值,可以表示整型和浮点型,并且表示范围几乎无穷大
  • object: 表示值是对象或null(null表示空对象,但是null == undefined会返回true)。我们还可以使用instanceof来具体判断是哪种对象
  • function:
  • symbol: 表示值是符号
let message = "string";
console.log(typeof(message));//string

字符串插值与模板字面量

他和linux中echo的用法类似,使用${}将一个其他类型的值转换成字符串并插入某一个字符串中

let value = 5;
let exponent = 'second';
let interpolatedString = value + ' to the ' + exponent +' power is ' + (value * value);

等同于
let interpolatedTemplateLiteral =
`${ value } to the ${ exponent } power is ${ value * value }`;

此外,模板也可以插入之前的值

let value = '';
function append()
{
value = `${value}abc`;
console.log(value);
}
append();//abc
append();//abcabc
append();//abcabcabc

此外,我们使用模板自变量传参时还可以让他每个插入当成一个参数
let a = 6
let b = 9
function simpleTag(strings, aValExpression, b, sum)
{
console.log(strings);
console.log(aValExpression);
console.log(b);
console.log(sum);
return 'foobar';
}

let result = `${a} + ${b} = ${a+b}`;
let tag_result = simpleTag`${a} + ${b} = ${a+b}`;
/*
输出
[ '', ' + ', ' = ', '' ]
6
9
15
*/
console.log(result);//6 + 9 = 15
console.log(tag_result);//foobar

我们可以使用String.raw标签函数来获取原始的模板字面量内容
console.log(`first line\nsecond line`);
//first line
//second line

console.log(String.raw`first line\nsecond line`);
//first line\nsecond line

但是对于实际的换行符不会转义
console.log(String.raw`first line
second line`);
//first line
//second line

Symbol

符号是原始值,并且符号实例是唯一且不可变的。符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险。

定义: 使用Symbol()函数初始化

let fooSymbol = Symbol('foo');
//foo是对符号的描述,可以通过这个字符串调试代码,但是这个参数和符号定义和标志无关

也可以不传参数
let bar = Symbol('bar');

可以通过Symbol.for()创建全局符号

let symbol = Symbol.for('foo');
console.log(typeof(symbol));//symbol

这个函数会将符号添加到全局符号表中,如果没有那么它会创建这个符号,如果有将会直接引用

并且全局符号和局部符号不等同

let local_symbol = Symbol('foo');
let global_symbol = Symbol.for('foo');

console.log(local_symbol == global_symbol);//false

可以使用Symbol.keyFor()查询全局符号.例如Symbol.keyFor(123);

Symbol的作用就是标识属性,下面来看一下它的使用场景

let Person = 
{
name: 'a'
};

let People =
{
name: 'b'
};
let target = {};
Object.assign(target, Person, People);
console.log(target);//{ name: 'b' }a的name消失了

//使用Symbol
let Person =
{
[Symbol('name')]: 'a'
};

let People =
{
[Symbol('name')]: 'b'
};

let target = {};
Object.assign(target, Person, People);
console.log(target);//{ [Symbol(name)]: 'a', [Symbol(name)]: 'b' }
这样合并时就可以保存两个对象的同名属性了,因为Symbol之间必定不相同,所以不会冲突

循环和with语句

基础的循环语句和c语言相同,

for-in

for-in是一种严格的迭代语句,用于枚举对象中非符号键属性(遍历一个对象中的属性)

语法: for(property in expression)

for (const propName in window)
{
document.write(propName);
}

这里使用for-in遍历了window的所有属性,这里的const不是必须的,但是为了保证局部变量不被修改,推荐使用const

对象的属性是无序的,所以多次遍历可能每次结果都不同

for-of

这个是用来遍历多个对象

for(const e of [2, 4, 6, 8])
{
document.write(e);
}

for-of会使用可迭代对象的next()方法按顺序迭代多个元素

此外,for循环中的break和continue可以使用标号,作用相当于goto,但是它不能任意跳转,只能跳出某个循环

let num = 0;

let num = 0;
out://表示第一层for循环,break out就是跳出这层循环
for(let i=0; i<10; i++)
{
for(let j=0; j<10; j++)
{
if(i == 5 && j == 5)
{
break out;
}
num++;
}
}
console.log(num);

with

with作用是把代码作用域设定为特定的对象.严格模式不允许使用with

例如

with(location)
{
let qs = search.substring(1);
let hostName = hostname;
let url = href;
}

否则要写
let qs = location.search.substring(1);
let hostName = hostname;
let url = href;