avatar

Catalog
JavaScript

js代码用标签包裹起来,js代码可以放在行内,body的后面,或者body之前,外部,但是通常我们会将js代码放在title的标签之下,但是如果这样的话,浏览器会先加载js代码,而不会先加载html的部分。由此,我们可以用window.onload = function(){js..代码}这种写法,但请不要忘记script标签。

attributes 属性

该属性是获取标签中的属性,列如class,id,和href之类的属性,如果一个标签中包含多个属性则使用attributes[num]获取的是第几个属性。该属性还可以有length和value属性。

cookie属性

是浏览器存储信息的东西document.cookie().

一、面向对象

面向对象的三大特性:继承,封装,多态。现在我要求我们要创建3个对象,但是我们看到是不是都有shoool属性,而且这些个属性还不带变的,所以我们由此引出来原型的概念。

javascript
let xx = {
name: 'xx',
age: 13,
shool: "hn"
};
let cc = {
name: 'cc',
age: 14,
shool: "hn"
};
let ww = {
name: 'ww',
age: 12,
shool: "hn"
};
//ok,下面我们用到面向对象的一种特性,封装。是不是简洁清晰。
function Person(name,age){
this.name = name;
this.age = age;
this.shool = "hn";
console.log(this.name);
console.log(this.age);
}
let ww = new Person("ww",13);
let cc = new Person("cc",34);

四、JS原型

二、JS原型

首先我们看一个例子:
javascript
function Person(age,name){
this.age = age;
this.name = name;
this.eat=function(){
console.log("我是构造函数中吃");
}
}
var p1 = new (13,"小红");
var p2 = new (15,"小明");
console.log(p1 == p2);//结果会是什么呢? false

为什么会是false呢?不都是构造函数中的方法嘛,因为实例化对象不同,所以调用的方法也不同,有一百个对象,那么就要调用一百次这个方法,那么这不浪费内存空间嘛,由此引出————原型(prototype)函数都有原型,不是只有构造函数才有原型。

续—

javascript
// 说明如果这个对象中没有这个属性,那么就去它的原型中去寻找
// 构造函数
function Person(name, age) {
this.name = name;
}
// 构造函数中添加方法
Person.prototype.alertName = function () {
alert(this.name);
}
// 创建实例
var p = new Person('zs', 23);
// 向实例中添加方法
p.printName = function () {
console.log(this.name)
}
p.printName();
p.alertName();
// 原型链,没有toString方法去,隐式原型(也是一个对象)的隐式原型中去找
p.toString();
console.log(p instanceof Person)
原型的作用:数据共享,节省内存空间。
javascript
function Person(age,name){
this.name = name;
this.age = age;
}
//向原型中添加方法
Person.prototype.eat=function(){
console.log("我是原型中的方法");
}
var p1 = new (13,"小红");
var p2 = new (15,"小明");
p1.eat();
p2.eat();//这样我们就调用的是同一个方法了。

原型分为显示原型(prototype)和隐式原型(proto),每一个函数都会有一个显示原型,每一个实例对象都有一个隐式原型,实例对象的隐式原型和函数的显示原型相等

javascript
function Person(name,age){
this.name = 'zs',
this.age = 13
}
var p1 = new Person;
console.log(p1.__proto__ === Person.prototype)

原型链(最终结果:Object.Prototype)

首先我们实例化对象的时候,如果构造函数中没有对应的方法或者属性,那么我们就要到原型中去寻找。如过没有找到,就会报错,如果在构造函数中找到,则输出相应的结果。自身=>构造函数中的原型=>原型中构造函数中的原型

QQ图片20190209175749

1557765176243

javascript
function Person(){
this.name = 34;
this.age = 32;
}
Person.prototype.name = 450;
var p1 = new Person();
console.log(p1.name);//是34没错了

作用域链的作用域

javascript
function fn (callback) {
var age = 18d
callback();
}
fn(function () {
console.log(age);//此时发生错误,是因为作用域链,看的不是函数在哪里调用,而是在那里编写,因为不在fn内部编写所以发生错误
//作用域链发生预编译,所以age为undefined
//var age = 12;
//console.log(age);
})
原型继承: 利用原型,可以实现继承
javascript
function Animals () {
this.eat = function () {
console.log('animals can eating')
}
}
function Dog () {
this.bark = function () {
console.log('Dog bark')
}
}
Dog.prototype = new Animals ();
var hashiqi = new Dog ();
hashiqi.eat();
hashiqi.bark();
简单的原型继承
javascript
var parent = {name : 'zs',age : 16};
var student = Object.create(parent);
console.log(parent);
console.log(student);//student中的__prototype__(隐式原型指向parent)

利用简单的原型继承可以实现非常简单的原型继承,可以不用构造函数。因为每次要 写一次构造函数都会很麻烦。

三、JS dom 操作

众说周知JS其实可以分为两个大块,dom和bom部分,今天我们就来说说dom部分。document代表的是整个文档。

1. dom选择器
  1. document.getElementById();//在开发过程中我们并不太常使用这种方法来获取id属性
  2. document.getElementsByClassName()[]//类数组获取样式
  3. document.getElementsByTagName()[]//获取标签名类似一个数组,但不是一个数组,简单来说是类数组
  4. document.getElementByName()获取某些具有name属性的标签
  5. document.querySelectorAll()获取css选择器,有缺点,包括ie7和一下都没有
  6. document.querySelector()css选择器,同上。
2. dom节点类型
  • parentNode->父节点(body->html->document->null)

  • childNodes->子节点们

    javascript
      <div>
    <section></section>
    <span></span>
    <p></p>
    </div>
    <script>
    window.onload = function(){
    var odiv = document.getElementsByTagName("div")[0];
    console.log(odiv.childNodes.length);
    }
    </script>
    //猜猜结果是什么? 是7为什么呢?因为里面包含了文本节点,不可能是3的哟。
  • lastChild->最后一个子节点

  • fristChild->第一个子节点(这两个取决你是否换行,如果有则是文本节点)

  • nextSibling->后一个兄弟节点

  • previousSibling->前一个兄弟节点

3. 基于元素节点树的遍历

parentElement->父元素节点

children->当前元素子节点

fristElement->第一个元素节点

lastElement->最后一个元素节点(IE不兼容同上)

nextElementSibling/preElementSibling->后一个/前一个兄弟节点

4. 节点的四个属性
  1. nodeName->元素的标签名
  2. nodeValue->text节点或Comment节点的文本内容,可读写
  3. nodeType 该节点的类型
    • 元素节点——-1
    • 属性节点——–2
    • 文本节点———–3
    • 注释节点————-8
    • document———-9
    • DocumentFragment—-11
  4. Attributes 该节点的属性集合
5. 节点的增删改查
  1. 创建节点———–>createElement(“节点名称”);
  2. 创建文本节点————>createTextNode(“节点名称”)
  3. 删除节点—————> removeChild(“节点名称”);
  4. 增加节点—————->appendChild(“节点名称”)往后追加节点
    • insertBefore(节点1,节点2) //追加节点2 在节点1的前面
    • insertAfter()同上。

四、JS 正则部分

js中的正则又很多种方法不过常用的还是

test(),search() ,repleace() act..

1. 正则表达式模式
^ //g {4,11} /d /w (任意值/)
开始符号 类是与全局 最少是4次,最多为11次数字相当于区间 全为数字 全为字母,数字,下划线 任意一个值
$ [1-9] {4,}最少为4次 /D /W n+,n*,n?
结束符号 出现1-9中的任何一个数字 {,11}最多为11次 非数字 非数字,字母,数字,下划线 (至少一个)(至少0个或多个)(0个或多个)
2. 使用RegExp对象

在 JavaScript 中,RegExp 对象是一个预定义了属性和方法的正则表达式对象。

使用 test()

test() 方法是一个正则表达式方法。

test() 方法用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回 true,否则返回 false。

以下实例用于搜索字符串中的字符 “e”:

两种定义方式,如果不引入变量则使用最多的还是第一种方式,如果字符串中包含\则需要使用转义字符/\即可~

javascript
var patt = /e/g;
patt.test("this is best");//test的方法返回值是Boolean型如果查找对则返回true否则反之。

//要引入变量的话
let x = "abc";
let reg = new RegExp(x);
console.log(reg.test());
3. 举个例子(验证QQ号)
javascript
<script>
var input_qq = document.getElementById("text");
var btn = document.getElementById("btn");
btn.onclick = function(){
var input_value = input_qq.value;
var reg = /^[1-9][0-9]{4,11}$/g;
var result = reg.test(input_value);
if(result){
alert("正确的qq号");
}else{
alert("qq号不对哦");
}
}
</script>

五、target事件机制

有这么一个问题,有很多的li我需要点击某个li标签,来打印对应的li值。恩,这我们该怎么做?

首先我们先想到的就是就是获取的ul的id,然后获取所有的li,遍历每一个li,给li注册点击事件。弹出值。

但是在这里我们不能使用var来定义变量,我们需要使用let。这也是一种方法。但是我们可以使用target

html
<body>
<ul id='ul'>
<li>43</li>
<li>44</li>
<li>45</li>
<li>46</li>
<li>47</li>
<li>48</li>
<li>49</li>
<li>50</li>
</ul>
<script>
let ul = document.getElementById('ul');
let li = ul.children;
ul.onclick = function(e){
console.log(e.target.innerText);
}
</script>
</body>

这里我们无需为li注册点击事件,如果我们li没有点击事件的话,我们就是向上一层寻找事件,上一层再没有再找,这就是事件冒泡。target 属性规定哪个 DOM 元素触发了该事件。这个 event 参数来自事件绑定函数。而这个e就相当于我们点击了哪一个li。

六、作用域和内存问题

ECMAScript变量包含两种不同的数据类型的值,基本数据类型和引用数据类型,基本数据类型:String、Blooean

Number 、null 、 undefined,引用类型包括:Object、Symbol。应用类型的值是保存在内存中的对象,对其引用类型的值我们可以添加属性和方法,也可以删除属性和方法。但是我们的基本数据类型的值则是不行。

传递参数

函数中的参数都是按照值传递的,不像变量有按值和按引用传递,而参数只能按照值传递。

对象也是按值传递的,当在函数内部重写obj,这个变量引用的就是一个局部对象,函数执行完就会立即被销毁。

javascript
function setName(obj){
obj.name = 'zs';
obj = new Object();
obj.name = 'ls';
}
var person = new Object();
setName(person)
alert(person.name);
对象

对象赋值时地址赋值,两个对象指向的时同一内存空间,所以当我们改变其中的一个对象的时候,另外一个也会发生改变

javascript
var obj = {
name: 'zs'
}
var obj2 = obj
obj2.name = 'ls'
console.log(obj.name) //ls
console.log(obj2.name) //ls
javascript
var a = {
name: 'zs',
age: 14
}
function fn(obj){
obj = {age: 15};
}
fn(a);
console.log(a)

以上的age的值依然为14,这是一开始,a 和obj都指向同一内存空间。但是这个时候改变了obj的指向。但是不会影响a所以a还是原始的指向

javascript
var a = 3;
function fn(a){
a = a + 1;
return a
}
console.log(fn(a)); //函数返回值
console.log(a) //全局对象a
作用域链
Javascript
function a(){
function b(){
function c(){

}
c()
}
b()
}
a()
a defined a.[[scope]] ----> 0:GO

a doing a.[[scope]] ----> 0:aAO
1:GO

b defined b.[[scope]] ----> 0:aAO
----> 1:GO

b doing b.[[scope]] ----> 0:bAO
1:aAO
2:GO

c defined c[[scope]] ----> 0:bAO
1:aAO
2:GO

C doing c.[[scope]] ----> 0:cAO
1:bAO
2:aAO
3:GO

a函数的执行才会发生b函数的定义,同理b函数的执行,发生c函数的定义

上面的代码解释了内层函数(站在其他函数上面看世界)是为什么访问到外层函数的变量,每一个函数在执行的前一刻都会产生一个执行期上下文(AO)。作用域链一层一层的往上面查找。

函数执行完会立即销毁作用域,则再次调用该函数会另外产生一个内存空间,但是若是函数中有函数被返回出去,则这个空间不会被销毁。

七、函数

函数的三种方式
  • 函数表达式
  • 函数声明
  • 构造函数
javascript
//第一种
var fn1 = function(){
console.log("函数表达式")
}
//第二种
function fn2(){
console.log("函数申明")
}
//第三种
var fn3 = new Function (){
console.log("构造函数")
}
回调函数

回调函数是一个作为变量传递给另外一个函数的函数,它在主体函数执行完之后执行。

八、预编译

imply global暗示全局变量,一切未经声明的变量都为全局变量归window所有

javascript
a = 3   //window.a
var b = c = d //window.c

在全局中声明的变量归window所有

Javascript
var a = 123  // window.a 123

预编译发生在函数执行的前一刻

大多数可以用一句话概括,变量声明提升,函数整体提升。在JavaScript中函数执行的时候都会发生预编译。

可以划分为四个步骤:

  • 生成AO(Active Object)对象(执行期上下文)
  • 找出形参和变量的声明,将形参和变量声明作为AO的属性,并且值为undefined。
  • 将实参值和形参的值统一。
  • 找出函数声明,值赋予函数体
javascript
function fn(a) {
console.log(a);
var a = 123;
console.log(a);
function a() {}
console.log(a);
var b = function () {}
console.log(b);
function d() {}
}
fn(1);
javascript
//第一步创建AO对象和赋值undefined
AO{
a: undefined,
b: undefined,
d: undefined
}
//第三步和第四步
AO{
a: function a(){},
b: undefined,
d: function d(){}
}

预编译不止发生在函数中,也同时发生在全局,也会生成一个对象GO(global Object)只不过没有将实参和形参相统一。其余步骤一样,先创建GO,再创建AO。

九、this

  • 全局作用域中,this指向Window
javascript
console.log(this)---------Window
  • 函数没有实例对象,函数预编译,this指向Window
javascript
function fn1 () {
console.log(this)
}
fn1();
  • 函数内部的this,是由谁调用了函数来决定的。
javascript
function Fn2 () {
console.log(this)
}
var f = new Fn2;
  • 对象中的this是指向这个对象。
javascript
var obj = {
name: 'zs',
getName: function () {
console.log(this.name);
}
}
obj.getName();
  • 利用call改变this的指向,第一个参数是this的指向,第二个是参数
javascript
function fn4 (name) {
console.log(this);
}
fn4.call({x:100},'zs')

十、隐式转换

在JavaScript中+和-号可以是运算符的连接,但是如果两边是字符串的话会有什么作用呢?

javascript
console.log("22"-"11"+"12")//1112

如果加号的两边或者一边是字符串则转换成string进行字符串拼接。但是如果是-号,则优先转换成number

十一、包装类对象和类型检测

(1)基础数据类型和引用类型,基础类型是不可以调用方法和添加属性的

javascript
var str = "hello"
console.log(str.length)//5
str.t = "world"

这里的t还有长度都是临时的对象,并不是真正的属性和方法。

(2)一般的类型检测会使用typeof 和 intanceof

  • typeof(确定,无法确定null类型,无法确定对象是属于一类的)
  • 测试类型 intanceof 判断是否为哪一种类型
javascript
console.log(typeof [1,3]) ---object
console.log(typeof null) ----object
console.log([1,2] intanceof Array)

(3) 除去number、string、null、undefined、Boolea这五种是属于基本数据类型,其余的为引用类型(又称复杂类型)如果我们构造函数中返回值类型不是基本数据类型,则不是我们创建的实例

Code
function Person(){
return [1,3,4];
}
var p1 = new Person();
console.log(p1 intanceof Person) // false

十二、严格模式

严格模式是 一种特殊的运行模式,它修复了部分语言的不足,更加增强了错误检查,并增强了安全性。

使用严格模式:”use strict”一些浏览器不知此严格模式的情况下,只会解析成字符串,所以不会有错误。

严格模式下不允许:

  • 不允许使用with
  • 不允许对象属性有相同的命名
  • 不允许使用delete运算符
  • 不允许eval,arguments变为关键字,不能作为变量名、函数名
  • 禁止八进制的字面量
  • eval成为独立的作用域

通过object.create(参数)创建一个空对象,这个对象原型指向该参数

Author: Yo
Link: https://powerlrl.gitee.io/2018/08/04/前端/笔记/JavaScript/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 谢谢你请我吃糖果
    谢谢你请我吃糖果

Comment