JavaScript入门笔记

JavaScript

1.js放在哪些位置

  1. 行间

    优点:非常直观,直接作用于你写的元素

    缺点:

    1.结构分析不清晰(html/css/js)

    2.无复用性

    3.维护不方便,后期修改不方便

  2. 内部

    优点:

    1.结构分离更清晰

    2.可以复用(当前页面)

    3.较利于维护和修改

    缺点:

    1.多页面之间无法复用

    2.多页面之间的维护修改较麻烦

  3. 外部(是推荐在工作中使用的方式)

    优点:

    1.结构彻底分离

    2.多页面进行复用

    3.后期维护修改非常方便

    缺点:

    1.增加请求数

一个script标签如果有src,那么如果再在标签中写js代码则不会被执行,而只会执行src文件中的js代码

script标签最合适的放置位置

两种解决方案:

  1. 在<head>中的js代码,放置在window.onload(等待窗口加载完成)事件中

  2. 放在</body>标签前,让HTML结构先行加载完成

注意事项:

如果js的代码比较庞大,需要较长的时间读取,会影响页面的加载,造成页面长时间空白。

从用户体验的角度来说,我们应该避免这样的情况,长时间空白会让用户觉得打开速度很慢,从而造成用户流失。

声明变量

使用关键字声明变量(关键字:js中定义好的有一定特殊意义的单词)

var

声明:var 变量名

js中的属性

操作属性的方法:

  1. 点 -- .

  2. 方括号 -- []

方括号中可以填入需要计算的东西,或者不符合标识符规范的

两种属性操作可以一起使用

属性的读操作

console.log(属性)

常用属性:

id

className

value

style(行间属性)

background

color

width

height

cssText

innerHTML

href

src

tagName

数据类型

简单数据类型

number

string

Boolean

null

undefined

symbol

复杂数据类型

object

传值和传址

如果是简单类型,进行传值运算

复杂类型进行传址运算

强制类型转换

parseInt :强制转换为整数

如果首位字符是非数字字符,那么输出NaN,表示转换失败

parseFloat:强转为小数

number:强转为数字,只要字符串中含有非数字,就会输出NaN

隐式类型转换

在加号运算符周围有时会将字符串转换成数字进行数学运算

运算符

运算符左右两侧若都为数字,则正常进行数学运算

加法减法....

乘法:左右两边若有一个是NaN,则结果为NaN

true为1

false为0

null为0

如果有一侧不是number类型的,则(根据相应规则)转换为数字进行计算

除法:左右两边若有一个是NaN,则结果为NaN

如果0作为除数,则返回NaN

一元操作符

只能操作一个值得到操作符

一元加运算符:如果操作数是number类型的时候,正好放在数值前面,对其完全没有影响

如果操作数是string、true、false、null、undefined,则(根据对应规则)转为数字类型

减号同理,只是转换为负数

全等、全不等

=== 全等

比较两端的类型和值

只有类型和值都一致才返回true,否则false

!== 全不等

只有类型和值都不一致才返回true,否则false

for ... in循环

声明一个key变量用于代表obj里面的key

对象中有几个属性就执行几次

for(var key in obj)

var obj = {
    x:20,
    y:30,
    z:40
}
for(var v in obj)
{
    console.log(obj[v]);    
}

函数

函数声明和函数表达式

function fn(){
    代码块
}//函数声明
var fn = function(){
    代码块
}//函数表达式

立即执行函数:(通常只执行一次)

(function(a.b){
    代码块;
})(123,456);

匿名函数不可以直接创建

函数的调用:

  1. 函数名称();

  2. 事件调用

标识符:变量名、函数名(函数参数)、属性名

标识符要遵守同一个命名规则(驼峰)

函数的事件调用和非事件调用

事件调用:

document.onclick = fn;

非事件调用:

fn();

函数也是对象

arguments:获取实参,不限个数

获取非行间样式

getComputedStyle

get Computed Style

获取 计算后 样式

用法示例:

var wid = getComputedStyle(document.querySelector('div'))[width];

有兼容性问题: IE-8 以下浏览器 不支持

函数、return 可以帮助我们解决兼容问题

对象

var obj = new Object;

向对象中添加属性

属性名.属性值

删除对象的属性:

delete 对象名.属性名;

对象的属性名不强制要求遵守标识符的规范

什么乱七八糟的名字都可以使用

但是使用时还是尽量按照标识符规范去做

如果要使用特殊的属性名,不能采用 . 的方式来操作

语法:对象["属性名"] = 属性值

读取时也需要采用这种方式

obj["123"] = 789;

console.log(obj["123"]);

使用[]这种形式去操作属性,更加的灵活

在[]中可以直接传递一个变量,这样变量值是多少就会读取那个属性

obj["nihao"] = "你好";
var n = "nihao";
console.log(obj[n]);
//结果:你好

JS对象的属性值可以是任意的数据类型,甚至也可以是一个对象,甚至甚至还可以是一个函数(方法)

in运算符

通过该运算符可以检查一个对象中是否含有指定的属性

如果有则返回true,没有则返回false

语法:

"属性名" in 对象

console.log("name" in obj);

基本和引用数据类型

基本:string number Boolean Null undefined

引用:object

js中变量都是保存在栈内存中

基本数据类型的值直接在栈内存中存储

各值之间独立存在,不会互相影响

引用数据类型(对象)直接保存在堆内存中,每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而变量保存的是对象的内存地址(对象的引用),如果两个变量保存的是同一个对象引用,当一个通过一个变量修改属性时,另一个也会受到影响

比较基本数据类型时,比较的是值

比较引用数据类型时,比较的是内存地址

对象字面量

一般创建对象:var obj = new Object;

使用对象字面量来创建对象:var obj = {};

可以在创建对象时,直接指定对象中的属性

语法:{属性名:属性值,属性名:属性值,......}

全局作用域、函数作用域

1.直接编写在script标签中的JS代码,都在全局作用域

全局作用域在页面打开时创建,在页面关闭时销毁

在全局作用域中有一个全局对象window,

它代表的是一个浏览器的窗口,它由浏览器创建,我们可以直接使用

在全局作用域中所有创建的变量都会作为window对象的属性保存

创建的函数都会作为window对象的方法保存

变量的声明提前

使用var关键字声明的变量,会在所有的代码执行之前被声明

但是如果变量声明时不使用var关键字,则变量不会被声明提前

函数的声明提前

使用函数声明形式创建的函数function 函数(){}

它会在所有代码执行之前就被创建

使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用

全局作用域中的变量都是全局变量

2.函数作用域

this

解析器在调用函数每次都会向函数内部传递进一个隐含的参数,

这个隐含的参数就是this,this指向的是一个对象,

这个对象我们称为函数执行的上下文对象,

根据函数的调用方式不同,this会智商不同的对象

1.以函数的形式调用时,this永远都是window

2.以方法的形式调用时,this就是调用方法的那个对象

使用this可以更加灵活地操作方法,使得在调用不同对象的属性时能成功调到不同对象的属性,而不是固定的值。

使用工厂模式创建对象

function createDog(name,)
{
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.sayHello = function(){
        alert("你好");
    }
    return obj;
}
var xia = createDog("夏+1","睡觉","汪汪~~");

使用构造函数创建对象

创建一个构造函数,专门用来创建Person对象

构造函数就是一个普通的函数,创建方式和普通函数没有区别,

不同的是构造函数习惯上首字母大写

构造函数和普通函数的区别就是调用方式的不同

普通函数就是直接调用,而构造函数需要使用new关键字来调用

构造函数执行流程:

  1. 立即创建一个新的对象

  2. 将新建的对象设置为函数中的this,在构造函数中可以使用this来引用新建的对象

  3. 逐行执行函数中的代码

  4. 将新建的对象作为返回值返回

function Person(){
    
}
var per = new Person();
console.log(per);

使用instanceof可以检查一个对象是否是一个类的实例

console.log(per instanceof Person);

原型prototype

我们所创建的每一个函数,解析器都会向函数中添加一个prototype

这个属性对应着一个对象,这个对象就是我们所谓的原型对象

如果函数作为普通函数调用,prototype没有任何作用

当函数通过构造函数调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,可以通过__proto__来访问该属性

console.log(obj.__proto__);

创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了

可以使用hasOwnProperty()来检查对象自身中是否含有某属性

使用该方法只有当对象自身中含有属性时,才会返回true

原型对象也是对象,所以它也有原型,

当我们使用一个对象的属性或者方法时,如果原型对象中有,则使用,

如果没有则去原型的原型中寻找,直到找到Object对象的原型,

Object对象的原型没有原型,如果在Object中依然没有找到,则返回undefined

toString

输出一个对象的信息时,输出的是对象中的toString,所以如果要修改输出信息,就修改对象的toString。

垃圾回收

当一个对象没有任何的变量或者属性对它进行引用,此时我们将永远无法操作对象

此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢

所以这种垃圾必须进行清理

在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收的操作

我们需要做的只是将不再使用的对象设置null即可

数组(Array)

数组也是对象

创建数组对象:

var arr = new Array();

var arr = [];

var arr = [1,2,3...];

var arr = new Array(10,20,30);

对数组的操作

添加数组中的元素:和C差不多

获取数组的长度:和java差不多,使用 length

console.log(arr.length);

使用length可以获取到连续的数组的元素个数(长度)

对于非连续的数组,使用length会获取到数组中最大的索引+1

所以尽量不要创建非连续数组

修改length的长度:

arr.length = 长度;

如果修改的length大于原长度,则多出部分会空出来

如果修改的length小于原长度,则多出元素会被删除

小技巧:向数组最后一个位置添加元素:

arr[arr.length] = 值;

数组中的元素可以是任意的数据类型甚至对象和函数

push(): 该方法可以向数组的末尾添加一个或多个元素,并返回数组的新的长度。可以将要添加的元素作为方法的参数传递。

pop(): 删除数组的最后一个元素

unshift(): 向数组开头添加一个或多个元素,并返回新的数组长度。向前边插入一个元素以后,其他的元素索引会依次调整

shift(): 删除数组的第一个元素,并将被删除的元素作为返回值返回

forEach

JS提供forEach方法来遍历数组,这个方法只支持IE8以上的浏览器

forEach方法需要一个函数作为参数

像这种函数,由我们创建但是不由我们调用的,称为回调函数

数组中有几个元素函数就会执行几次,每次执行时,浏览器会将遍历到的元素以实参的形式传递进来,我们可以定义形参,来读取这些内容

浏览器会在回调函数中传递3个参数:

第一个参数,就是当前正在遍历的元素

第二个参数,就是当前正在遍历的元素的索引

第三个参数,就是正在遍历的数组

arr.forEach(function(){
    console.log("hello");
});

slice && splice

slice

从某个已有的数组返回选定的元素(从数组提取指定元素)

参数:

  1. 截取开始的位置的索引,包含开始索引

  2. 截取结束的位置的索引,不包含结束索引

    第二个参数可以省略不写,此时会截取从开始索引往后的所有 元素

    索引可以传递一个负值,如果传入一个负值,则从后往前计算

该方法不会改变原数组,而是将截取到的元素封装到一个新数组中返回

var result = arr.slice(0,2);
console.log(result);

splice

可以用于删除数组中指定元素

使用splice()会影响到原数组,会将指定元素从原数组中删除

并将被删除的元素作为返回值返回

参数:

  1. 表示开始位置的索引

  2. 表示删除的数量

  3. 第三个及以后:

    可以传递一些新的元素,这些元素将会自动插入到开始位置

arr.splice(0,2);

Array剩余方法

concat():连接两个或多个数组,并将新的数组返回

该方法不会对原数组产生影响

var arr1 = [1,2,3];
var arr2 = [4,5,6];
var arr3....
var result = arr1.concat(arr2,arr3,.....);

join()该方法可以将数组转换为一个字符串

该方法不会对原数组产生影响,而是将转换后的字符串作为结果返回

在join()中可以指定一个字符串作为参数,这个字符串将会成为数组中元素的连接符,如果不指定,默认使用 “,” 作为连接符

var result = arr.join();

reverse():反转数组

该方法将会直接修改原数组

arr.reverse();

sort():可以对数组进行排序

会影响原数组,默认按照Unicode编码进行排序

即使对于纯数字的数组,使用sort()排序时,也会按照Unicode编码来排序,所以对数字进行排序时,可能会得到错误的结果

我们可以自己来指定排序的规则

我们可以在sort()添加一个回调函数,来指定排序规则

回调函数中需要定义两个形参,

浏览器会分别使用数组中的元素作为实参去调用回调函数

使用哪个元素调用不确定,但肯定的是在数组中a一定字b前边

浏览器会根据回调函数的返回值来决定元素的顺序,

如果返回一个大于0的值,则元素会交换位置

如果返回一个小于0的值,则元素位置不变

如果返回一个等于0的值,则认为两个元素相等,也不交换位置

arr = [3,5,2,1,4];
arr.sort(function(a,b){
    return a-b;//升序a-b,降序b-a
    /*
    其原理为以下的简化:
    if(a>b)
    {
        return 1;
    }else if(a<b)
    {
        return -1;
    }else
    {
        return 0;
    }
    */
});

函数对象的方法:call() && apply()

这两个方法都是函数对象的方法,需要通过函数对象来调用

当对函数调用call()和apply()都会调用函数执行

在调用call()和apply()可以将一个对象指定为第一个参数

此时这个对象将会成为函数执行时的this

call()方法可以将实参在对象之后依次传递

apply()方法需要将实参封装到一个数组中统一传递

function fun(){
    alert("我是fun函数");
}
var obj = {};
fun.call(obj);

总结:

this的情况:

  1. 以函数的形式调用时,this永远都是window

  2. 以方法的形式调用时,this是调用方法的对象

  3. 以构造函数的形式调用时,this是新创建的那个对象

  4. 使用call和apply调用时,this是指定的那个对象

arguments

在调用函数时,浏览器每次都会传递进两个隐含的参数:

  1. 函数的上下文对象this

  2. 封装实参的对象arguments

    arguments是一个类数组对象,它也可以通过索引来操作数据, 也可以获取长度

    在调用函数时,我们所传递的实参都会在arguments中保存。

    arguments.length可以用来获取实参的长度

    我们即使不定义形参,也可以通过arguments来使用实参

    只不过比较麻烦

    arguments[0] 表示第一个实参

    arguments[1] 表示第二个实参...

    它里面有一个属性叫做callee,这个属性对应一个函数对象,就是当前正在指向的函数的对象

function fun(){
    console.log(argument);
}

Date

在JS中使用Date对象来表示一个时间

如果直接使用构造函数创建一个对象,则会封装为当前代码执行的时间

var d = new Date();

在构造函数中传递一个表示时间的字符串作为参数

日期的格式:月份/日/年 时:分:秒

var d2 = new Date("04/15/2022 16:43:30");

getDate() 获取当前日期对象是几号

getDay() 获取当前日期对象是周几

getMonth()获取...

getFullYear()获取...

 

Math

Math和其他的对象不同,它不是一个构造函数

它属于一个工具类,不用创建对象,它里面封装了数学运算相关的属性和方法

 

 

包装类

JS为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象

String()

可以将基本数据类型字符串转换为String对象

Number()

可以将基本数据类型数值转换为Number对象

Boolean()

可以将基本数据类型布尔值转换为Boolean对象

var num = new Numboer(3);

在实际开发中不会使用基本数据类型的对象,

如果使用基本数据类型的对象,在做一些比较时可能会带来一些不可预期的结果

小知识:对象转换成布尔值都是true

方法和属性只能添加给对象,不能添加给基本数据类型

当我们对一些基本数据类型的值去调用属性和方法时,

浏览器会临时使用包装类将其转换为对象,然后再调用对象的属性和 方法。

调用完后,再将其转换为基本数据类型

总结:包装类是浏览器底层自己用的,

String对象(包装类之一)

 

String对象的方法:

 

 

正则表达式

正则表达式用于定义一些字符串的规则,

计算机可以根据正则表达式,来检查一个字符串是否符合规则,

获取将字符串中符合规则的内容提取出来

创建正则表达式:

  1. 使用构造函数创建

语法:var 变量 = new RegExp("正则表达式","匹配模式");

var reg = new RegExp();

使用typeof检查正则对象,会返回object

正则表达式的方法:test()

使用这个方法可以用来检查一个字符串是否符合正则表达式的规则

如果符合,返回true,否则返回false

var reg = new RegExp("a");
var str = "a";
var result = reg.test(str);

这个正则表达式可以来检查一个字符串是否含有"a"

  1. 使用字面量来创建

语法:var 变量 = /正则表达式/匹配模式

使用字面量的方式创建更加简单

使用构造函数创建更加灵活

通过一些实例了解和、或用法

检查字符串是否含有a或者含有b:

var reg = /a|b/

使用|表示或者的意思

创建一个正则表达式检查一个字符串中是否含有小写字母

var reg = /[abcdefghijklmnopqrstuvwxyz]/;

或者:var reg = /[a-z]/;

[]里的内容也是或的关系([ab] == a|b)

[a-z] 任意小写字母

[A-Z] 任意大写字母

[A-z] 任意字母

[^abc] 任何不在方括号中的字母

将字符串拆分为一个数组

方法中可以传递一个正则表达式作为参数,这样方法会根据正则表达式去拆分字符串

根据任意字母来将字符串拆分

var str = "1a2b3c4d5e6f7"
var result = str.split(/[A-z]/);
console.log(result);
//结果:"1,2,3,4,5,6,7"

search()

可以搜索字符串中是否含有指定内容

如果搜索到指定内容,则会返回第一次出现的索引,如果没有搜索到,返回-1

var str = "hello";
result = str.search("abcd");
console.log(result);
//结果:-1

搜索字符串中是否含有abc 或 aec 或 afc

var str = "hello";
result = str.search(/a[bef]c/);

match():可以根据正则表达式,从一个字符串中将符合条件的内容提取出来

默认情况下我们的match只会找到第一个符合条件的内容,找到以后就停止检索

我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容

match()会将匹配到的内容封装到一个数组中返回,即使只返回一个结果

全局匹配模式:g

忽略大小写匹配模式:i

replace()

可以将字符串中指定内容替换为新的内容

参数:

  1. 被替换的内容,可以接受一个正则表达式作为参数

  2. 新的内容

split()

可以将一个字符串拆分为一个数组

方法中可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆分字符串

var result = str.split(/[A-z]/);

正则表达式的语法

量词

通过量词可以设置一个内容出现的次数

量词只对它前边的一个内容起作用,除非加括号

{n} 正好出现 n 次

{m,n} 出现 m-n 次

var reg = /a{3}/;

var reg = /(ab){3}/;

出现1-3次:

var reg = /a{1,3}/;

所有量词:

 

在正则表达式中用\作为转义字符

例:\.表示.

\\表示\

元字符:有特殊含义的字符

去除字符串前后的空格:

去除空格就是使用""来替换空格

var str = "           hello world      ";
str = str.replace(/\s/g,"");
//结果:helloworld
//这种会去除全部空格
var str = "           hello world      ";
str = str.replace(/^\s*|\s*$/g,"");
//结果:hello world

宿主对象

DOM

Document Object Model文档对象模型

JS中通过DOM来对HTML文档进行操作,只要理解了DOM就可以随心所欲地操作WEB页面

文档:文档表示的是整个HTML网页文档

对象:表示将网页中每一个部分转换为一个对象

模型:使用模型来表示对象之间的关系,这样方便我们获取对象

节点:构成HTML文档最基本的单元

事件

用户和浏览器之间的交互行为

比如:点击按钮,鼠标移动,关闭窗口......

我们可以在事件对应的属性中设置一些JS代码,这样当事件被触发时,这些代码将会执行

<button id="btn" οnclick="alert('讨厌,你点我干嘛!');">
    我是一个按钮
</button>

这种写法成为结构和行为耦合,不方便维护,不推荐使用

我们应将js代码写到最下面script标签中

这样写是为了保证页面加载完成后再执行js代码

onload事件会在整个页面加载完成之后才触发

为window绑定一个onload事件

该事件对应的响应函数将会在页面加载完成之后执行

这样可以确保我们的代码执行时所有的DOM对象已经加载完毕了

window.onload = function(){
    var btn = document.getElementById("btn");
    btn.onclick = function(){
        alert("hello");
    }
}

(该函数一般在script标签没有在最下边时使用)

获取元素节点的一些方法(通过document对象调用)

ElementsByTagName:通过标签名来获取一组元素节点对象,这个方法会给我们返回一个类数组对象,所有查询到的对象都会封装到对象中

getElementsByTagName:通过标签名来获取一组元素节点对象,这个方法会给我们返回一个类数组对象,所有查询到的对象都会封装到对象中

getElementsByName:通过name属性获取一组元素节点对象

元素对象的一些方法

innerHTML:用于获取元素内部的HTML代码

对于单标签,这个属性没有意义

innerText:该属性可以获取到元素内部的文本内容,它和innerHTML类似,不同的是它会自动将html标签去除

对于单标签没意义。

所以如果需要读取元素节点属性,直接使用元素.属性名

例如:元素.id 元素.name 元素.value

注意:class属性不能采用这种方式

读取class属性时需要使用 元素.className

要修改一个元素的属性:

元素.属性 = 属性值

获取元素节点的子节点(通过具体的元素节点调用)

1.getElementsByTagName()

方法,返回当前节点的指定标签名后代节点

2.childNodes

属性,表示当前节点的所有子节点

childNodes属性会获取包括文本节点在内的所有节点

3.firstChild

属性,表示当前节点的第一个子节点(包括空白文本节点)

4.lastChild

属性,表示当前节点的最后一个子节点

5.children

属性,表示当前节点的所有子元素(没有空格等)

6.firstElementChild

获取当前元素的第一个子元素(不支持IE8及以下的浏览器,如果需要兼容尽量不要使用)

获取父节点和兄弟节点

通过具体的节点调用

1.parentNode

属性,表示当前节点的父节点

2.previousSibling

属性,表示当前节点的前一个兄弟节点(也可能获取空白文本)

3.nextSibling

属性,表示当前节点的后一个兄弟节点

4.previousElementSibling

类似previousSibling,不会获取空白文本(ie8不兼容)

读取value属性值

var a = document.getElementById("username");

修改value属性值

var a = document.getElementById("username");
a.value = "你瞅啥";

document.body:body的引用

document.documentElement:html根标签

document.all:代表页面中的所有元素

根据元素的class属性值查询一组元素节点对象

getElementsByClassName()可以根据class属性值来获取一组元素节点对象,但是该方法不支持ie8及以下浏览器

document.querySelector()

需要一个选择器的字符串作为参数,可以根据一个CSS选择器来查询一个元素节点对象

虽然IE8中没有getElementsByClassName()但是可以使用querySelector()

使用该方法总会返回唯一的一个元素,如果满足条件的元素有多个,那么它只会返回第一个

document.querySelectorAll()

这个方法和querySelector()用法类似,不同的是它会将符合条件的元素封装到一个数组中返回

DOM的增删改查

document.createElement()

可以用于创建一个元素节点对象,它需要一个标签名作为参数,将会根据该标签名创建元素节点对象,并将创建好的对象作为返回值返回

document.createTextNode()

可以用来创建一个文本节点对象,需要一个文本内容作为参数,将会根据该内容创建文本节点,并将新的节点返回

appendChild()

向一个父节点中添加一个新的子节点

用法:父节点.appendChild(子节点);

insertBefore()

可以在指定的子节点前插入新的子节点

语法:父节点.insertBefore(新节点,旧节点);

replaceChild()

可以使用指定的节点替换已有的子节点

语法:父节点.replaceChild(新节点,旧节点);

removeChild()

可以删除一个子节点

语法:父节点.removeChild(子节点);

如果不知道父节点:子节点.parentNode.removeChild(子节点)

使用innerHTML也能完成增删改的一些操作

div.innerHTML += "<li>hello<li>"

confirm()用于弹出一个带有确认和取消按钮的提示框,需要一个字符串作为参数,该字符串将会作为提示文字显示出来。

如果用户点击确认,返回true,点取消返回false

通过JS修改元素的样式

语法:元素.style.样式名 = 样式值

获取元素的样式

  1. 元素.currentStyle.样式名

    它可以用来读取当前元素正在显示的样式(只有IE支持)

  2. getComputedStyle()

    这个方法是window的方法,可以直接使用

    需要两个参数:

    1.要获取样式的元素

    2.可以传递一个伪元素,一般都传null

    该方法会返回一个对象对象中封装了当前元素的对应样式

    可以通过对象.样式名来读取样式

    如果获取的样式没有设置,则会读取到真实的值而不是默认值

    但是该方法不支持IE8及以下的浏览器

通过以上两种方法读取到的样式都是只读的,不能修改

事件event

事件对象

当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传进响应函数

在事件对象中封装了当前事件的一切相关信息,比如鼠标的坐标,比如键盘的哪个按键被按下,鼠标滚轮滚动的方向等等...

例:

clientX:获取鼠标指针的水平坐标

clientY:获取鼠标指针的垂直坐标

注:在IE8中,响应函数被触发时,浏览器不会传递事件对象,

在IE8及一下的浏览器中,是将事件对象作为window对象的属性保存的。

为了解决有的浏览器event直接作为对象而其他浏览器将event作为window的属性,可以写下面一行代码来解决兼容性问题:

event = event||window.event;

pageX/pageY:获取鼠标相对于当前页面的坐标

其和clientX/clientY的区别:pageX和pageY获取的是相对于当前页面的坐标,而clientX/clientY获取的是鼠标在相对于整个页面(可能大于一页)的最左上角的坐标

这两个属性很好用,但是在IE8中不支持,如果要兼容IE8,则不要使用

Crome认为浏览器的滚动条是body的,可以通过body.scrollTop来获取

获取滚动条滚动的距离:var st = document.body.scrollTop;

而火狐等浏览器认为浏览器的滚动条是html的,所以这些浏览器这样获取:

var st = document.documentElement.scrolltTop;

事件的冒泡(Bubble)

所谓的冒泡指的是事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发

在开发中大部分冒泡都是非常有用的,如果不希望发生事件冒泡可以通过事件对象来取消冒泡

event.cancleBBubble = true;将事件对象的cancleBubble设置为true,即可取消冒泡

事件的委派

我们希望,只绑定一次事件,即可应用到多个元素上,即使元素是后添加的,我们可以尝试将其绑定经给元素的共同的祖先

事件的委派,指将事件统一绑定给元素的共同的祖先,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件

事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能

target:event中的target表示的触发事件的对象

if(event.target.className == "link"){
    alert("我是ul的单机响应函数");
}

事件的绑定

使用 对象.事件 = 函数 的形式绑定响应函数,只能同时为一个元素的一个事件绑定一个响应函数,不能绑定多个,如果绑定了多个,则后边会覆盖掉前边的

addEventListener()

通过这个方法也可以为元素绑定响应函数

参数:

1.事件的字符串,不要on

2.回调函数,当事件触发时该函数会被调用

3.是否在捕获阶段触发事件,需要一个布尔值 ,一般都传false

btn.addEventListener("click",function(){
    alert(1);
},false);
btn.addEventListener("click",function(){
    alert(2);
},false);
btn.addEventListener("click",function(){
    alert(3);
},false);
//执行结果:1 2 3

attachEvent()

在IE8中可以使用attachEvent()来绑定事件

参数:

1.事件的字符串,要on

2.回调函数

这个方法也可以同时为一个事件绑定多个处理函数,

不同的是它是后绑定先执行,执行顺序和addEventListener()相反

btn.attachEvent("onclick",function(){
    alert(1);
})
btn.attachEvent("onclick",function(){
    alert(2);
})
btn.attachEvent("onclick",function(){
    alert(3);
})
//执行结果:3 2 1

定义一个函数,用来为指定元素绑定响应函数

说明:addEvent Listener()中的this,是绑定事件的对象,attachEvent()中的this,是window

需要统一两个方法this

参数:

obj 要绑定事件的对象

eventStr 事件的字符串(不要on)

callback 回调函数

function bind(obj,eventStr,callback(){
    if(obj.addEventListener)
    {
        //大部分浏览器兼容的方式
        obj.addEventListener(eventStr,callback,false);
    }else{
        //IE8及以下
        obj.attachEvent("on"+eventStr,callback);
    }
});

this是谁由调用方式决定

callback.call(obj)

在匿名函数中调用回调函数

function bind(obj,eventStr,callback(){
    
    obj.attachEvent("on"+eventStr,function(){
        callback.call(obj);
    });
    
});

事件的传播

关于事件的传播网景公司和微软公司有不同的理解

微软公司认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后再向当前元素的祖先元素上传播,也就是说事件应该在冒泡阶段执行。

网景公司认为事件应该is由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素的事件,然后再向内传播给后代元素,这个阶段称为捕获阶段

W3C综合了两个公司的方案,将事件的传播分为了三个阶段:

1.捕获阶段

在捕获阶段时从最外层的祖先元素向目标元素进行事件的捕获,但是默认此时不会触发事件。

2.目标阶段

事件捕获到目标元素,捕获结束开始在目标元素上执行触发事件

3.冒泡阶段

事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件。

如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true.但是一般情况下我们不会希望在捕获阶段执行触发事件,所以这个参数一般都是false.

function bind(obj,eventStr,callback(){
    obj.addEventListener(eventStr,callback,true);
});

BOM(browser object model)

浏览器对象模型

BOM可以使我们通过JS来操作浏览器

在BOM中为我们提供了一组对象,用来完成对浏览器的操作

BOM对象:

Window

代表的是整个浏览器的窗口,同时window也是网页中的全局对象

Navigator

代表当前的浏览器信息,通过该对象可以来识别不同的浏览器

由于历史原因,Navigator对象中的大部分属性都已经不能帮助我们识别 浏览器了

一般我们只会使用userAgent来判断浏览器的信息

userAgent是一个字符串,这个字符串中包含有用来扫描浏览器信息的内 容,不同的浏览器会有不同的userAgent

console.log(navigator.userAgent);

在IE11中已经将微软和IE相关的标识都去除了,所以我们基本已经不能通 过userAgent来识别一个浏览器是否是IE了

Location

代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者 操作浏览器跳转页面

如果直接将location属性修改为一个完整的路径,或相对路径,则页面会 自动跳转到该路径,并且会生成相应的历史记录

 

 

如果在reload方法中传递一个true作为参数,则会强制清空缓存刷新页面。

replace会替换页面,不会生成历史记录,不能使用回退按钮回退

History

代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录,即向 前向后翻页。

由于隐私的原因,该对象不能获取到具体的历史记录,只能操作浏览器 向前或者向后翻页,而且该操作只在当次访问时有效

属性:length,返回浏览器历史列表中的URL数量

方法:

1.back() 加载history列表中前一个URL

2.forward()加载history列表中下一个URL

3.go()加载history列表中的某个具体页面

go的参数:一个整数,1表示向前跳转一个页面,相当于forward(),2 表示向前跳转两个页面,-1表示向后跳转一个页面,以此类推

Screen

代表用户的屏幕信息,通过该对象可以获取到用户的显示器的相关信息

这些BOM对象在浏览器中都是作为window对象的属性保存的,可以通过window对象来使用,也可以直接使用

定时器

几个window对象的属性

setInterval():定时调用,可以将一个函数每隔一段时间执行一次

参数:

1.回调函数,该函数会每隔一段时间被调用一次

2.每次调用间隔的时间,单位是毫秒

var num = 1;
var timer = setInterval(function(){
    count.innerHTML = num++;
},1000);

返回值:返回一个number类型的数据,这个数字用来作为定时器的唯一标识

clearInterval()可以用来关闭一个定时器

方法中需要一个定时器的标识作为参数,这样将关闭标识对应的定时器

if(num == 11)
    {
        clearInterval(timer);
    }

setTimeout():延时调用,一个函数不马上执行个,而是隔一段时间后再执行,而且只会执行一次

var num = 0;
setTimeout(function(){
    console.log(num++);
},3000);

使用clearTimeout()来关闭一个延时调用,用法同clearInterval()。

延时调用和定时调用实际上是可以互相代替的,在开发过程中可以根据自己的需要去选择

类的操作

通过style属性来修改元素的样式,每修改一个样式,浏览器就需要重新渲染一次页面,这样执行的性能是比较差的,而且这种形式当我们要修改多个样式时,也不太方便

怎么样通过一行代码来修改多个样式?

.b1{
    width:100px;
    height:100px;
    background-color:red;
}
.b2{
    width:200px;
    height:200px;
    background-color:yellow;
}
box.className = "b2";

可以通过修改元素的class属性来间接修改样式,这样一来我们只需要修改一次,即可同时修改多个样式,并且这种方式可以使表现和行为进一步分离

定义一个函数,用来向一个元素中添加指定的class属性值:

参数:

obj 要添加的class属性的元素

cn 要添加的class值

function addClass(obj,cn){
    if(!hasClass(obj,cn)){
        obj.className += " "+cn;
    }
}

判断一个元素中是否含有指定的class属性值

如果有该class,则返回true,否则返回false

function hasClass(obj,cn){
    var reg = new RegExp("\\b"+cn+"\\b");
    return reg.test(obj.className);
}

删除一个元素中指定的class属性

function removeClass(obj,cn){
    var reg = new RegExp("\\b"+cn+"\\b");
    obj.className = obj.className.replace(reg,"");
}

如果元素中有该类,则删除如果元素中没有该类,则添加

function toggleClass(obj,cn){
    if(hasClass(obj,cn)){
        //有,则删除
        removeClass(obj,cn);
    }else{
        //没有,则添加
        addClass(obj,cn);
    }
}

JSON (JavaScript Object Notation)

JS对象表示法

JS中的对象只有JS自己认识,其他语言都不认识

JSON就是一个特殊格式的字符串,这个字符串可以被任意语言所识别,并且可以转换为任意语言中的对象,JSON在开发中主要用来进行数据的交互

JSON和JS对象的格式一样,只不过JSON字符串中的属性名必须加双引号

JSON对象分类:

  1. 对象{}

  2. 数组[]

JSON中允许的值:

  1. 字符串

  2. 数值

  3. 布尔值

  4. null

  5. 对象(不能是函数对象)

  6. 数组

将JSON字符串转换为JS中的对象:

JS为我们提供了一个工具类,就叫JSON

这个对象可以帮助我们将一个JSON转换为JS对象,可以将一个JS对象转换为JSON

JSON.parse()可以将以JSON字符串转换为js对象,它需要一个JSON字符串作为参数,会将该字符串转换为JS独享

JSON.stringify()可以将一个JS对象转换为JSON字符串需要一个js对象作为参数,会返回一个JSON字符串

var json = '{"name":"孙悟空","age":18,"gender":"男"}';
//json->js对象
var o = JSON.parse(json);
​
//js对象->JSON
var str = JSON.stringify(o);

JSON这个对象在IE7以下浏览器中不支持

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值