Some js knowledge|Youth training camp notes


theme: condensed-night-purple

highlight: a11y-dark

This is the 21st day I participated in the note creation activity of the "Fourth Youth Training Camp"

js running trilogy

  • Gramma analysis

  • Precompiled

  • Interpret and execute

Gramma analysis

Scan the whole text to see if there are grammatical errors, do not execute

Precompiled

prelude

  1. imply global implies a global variable : that is, any variable, if the variable is assigned without declaration, this variable is owned by the global object window eg: a = 123;js eg:var a = b = 123; //b未声明,window.b可以访问 //a声明了,window.a不可访问

  2. All declared global variables are all properties of window and js var a = 123; //相当于 window { a : 123 } window is global

The next time you visit a, you will check whether there is a in the window

Accessing a in the global scope is accessing window.ajs var a = 123; console.log(a) --> console.log(window.a)

Precompiled

Overall improvement of function declarations

The system always puts the function declaration at the top of the program logic

variable declaration hoisting

Variable declaration: var a;the system will bring the variable declaration to the front of the program

Precompilation happens just before function execution

Precompilation in the function system: 1. Create an AO object (Activation Object execution context) 2. Find the formal parameter and variable declaration, use the variable and formal parameter name as the AO attribute name, and the value is undefined 3. Set the actual parameter value and the formal Refer to Unity 4. Find the function declaration in the function body, and assign the value to the function body

```js function fn(a) { console.log(a); //out: function a() {}

var a = 123;        //预编译时将`var a`提前,执行`a = 123;`赋值语句

console.log(a);     //out: 123

function a() {}

console.log(a);     //out: 123

var b = function () {}

console.log(b);     //out: function () {}

function d () {}

}

fn(1);

// Precompilation process 1.AO{

}

2.AO{ a : undefined, b : undefined, }

3.AO{ a : 1, b : undefined, }

4.AO{ a : function a() {}, b : undefined, d : function d () {} }

//执行过程 AO{ a : 123, b : undefined, d : function d () {} } AO{ a : 123, b : function () {}, d : function d () {} } ```

练习

js function test(a,b) { console.log(a); c = 0; var c; a = 3; b = 2; console.log(b); function b () {} function d () {} console.log(b); } test(1); /*out: 1 2 2 */ AO { a :undefined --> 1 b :undefined --> function b () {} c :undefined d :undefined --> function d () {} } AO { a :1 --> 3 b :function b () {} --> 2 c :undefined --> 0 d :function d () {} }

js function test (a,b) { console.log(a); console.log(b); var b = 234; console.log(b); a = 123; console.log(a); function a() {} var a; b = 234; var b = function () {} console.log(a); console.log(b); } test(1); /*out: ƒ a() {} undefined 234 123 123 ƒ () {} */

全局预编译: 1. 创建GO对象(Global Object 执行期上下文) 2. 找变量声明,将变量作为GO属性名,值为undefined 3. 找函数声明,值赋予函数体

GO === window

```js GO { test : undefined --> function test () { ··· } --> 123 }

console.log(test); function test (test) { console.log(test); var test = 234; console.log(test); function test() {} }

AO { test : undefined --> 1 --> function test() {} --->234 }

test(1); var test = 123;

/*out: function test () { ··· } function test () {} 234 */ ```

练习

js var global = 100; function fn() { console.log(global); //out: 100 } fn();

```js GO { golbal : undefined ---> 100 fn : function () { ··· } } global = 100; function fn() { console.log(global); global = 200; console.log(global); var global = 300; } AO { global : undefined ---> 200 ---> 300 } fn(); var global;

//out: undefined // 200 ```

```js GO { a :undefined ---> 10 test : function () { ··· } c : 234 }

function test () { console.log(b); if(a) { var b = 100; } c = 234; console.log(c); } var a; AO { b : undefined } test(); a = 10; console.log(c);

//out:undefined // 234 // 234 ```

```js GO { a : undefined --> 100 demo : function demo () {} f : 123 } a = 100; function demo(e) { function e () {} arguments[0] = 2; console.log(e); if(a) { var b = 123; function c () { //猪都能做出来 } } var c; a = 10; var a; console.log(b); f = 123; console.log(c); console.log(a); } var a;

AO {
    a : undefined --> 10
    b : undefined
    c : undefined
    e : undefined --> 1 --> function e () {} --> 2
}
demo(1);
console.log(a);
console.log(f);

/* 2 undefined undefined (function c() {}) ----if里不能声明function 10 100 123 */
```

作用域

  1. 作用域定义:变量(变量作用域又称上下文)和函数生效(能被访问)的区域

  2. 全局、局部变量 函数里的是局部变量,外面的是全局变量 函数内部可以使用函数外面的变量

  3. 作用域的访问顺序 函数里面可以访问函数外的变量,但函数外部无法访问函数内部的变量

作用域精解 运行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象。 一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁。

查找变量:从作用域链的 顶端 依次向下查找

[[scope]]:每个JavaScript函数都是一个对象,对象有属性,对象中有些属性我们可以访问,但有些不可以,这些属性仅供JavaScript引擎存取,[[scope]]就是其中一个。[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合。

作用域链

[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式连接,我们把这种链式连接叫做作用域链

```js function a () { function b () { var b = 234; } var a = 123; b(); } var global = 100; a();

// a被定义时    a.[[scope]] --> 0 : GO
// a执行时      a.[[scope]] --> 0 : aAO
//                              1 : GO

// b被定义时      b.[[scope]] --> 0 : aAO
//                               1 : GO
// b执行时        b.[[scope]] --> 0 : bAO
//                                1 : aAO
//                                2 : GO

```

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述在这里插入图片描述

```js function a() { function b() { function c() {

}
    c();
}
b();

} a(); ``` 在这里插入图片描述

闭包

当内部函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄漏

js function a() { function b() { var bbb = 234; document.write(aaa); } var aaa = 123; return b; } var glob = 100; var demo = a(); demo(); // out: 123 在这里插入图片描述

```js function test () { var arr = []; for(var i = 0;i < 10;i ++){ arr[j] = function() { console.log(j); }

}
    return arr;
}
var myArr = test();
for(var j = 0;j < 10;j ++){
    myArr[j]();
}
// 因为i在test函数的AO里,arr里的函数共用一个i,所以执行后打印10个10
// 解决方法 :用闭包解决闭包,在函数自己的AO里可以取到想要的值
// 使用立即执行函数,将i的值传参进去
    for(var i = 0;i < 10;i ++){
        (function (j) {
            arr[j] = function() {
            console.log(j);
            }
        }(i))
    }

```

不用return实现 ```js var demo; function test () { var x = 123; function a () { console.log(x) } demo = a; } test(); demo();

```

闭包的作用

  1. 实现共有变量 eg:函数累加器 js function add() { var num = 0; function a () { console.log(++ num); } return a; } var myAdd = add(); myAdd(); myAdd(); myAdd();

  2. 可以做缓存(存储结构 eg:

在这里插入图片描述

  1. 可以实现封装,属性私有化 eg:Person();

```js function Deng(name,wife) { var prepareWife = 'xiaozhang';

this.name = name;
this.wife = wife;
this.divorce = function () {
    this.wife = prepareWife;
}
this.changPrepareWife = function (target) {
    prepareWife = target;
}
this.sayPrepareWife = function() {
    console.log(prepareWife);
}

} var deng = new Deng ('deng','xiaoliu'); ```

  1. 模块化开发,防止污染全局变量

闭包的防范

闭包会导致多个执行函数共用一个公有变量,如果不是特殊需要,应尽量防止这种情况发生

原型

定义

原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。 原型也是对象

```js //Person.prototype ----原型 产生时就已定义好 //Person.prototype = {} 是祖先 Person.prototype.name = 'hehe'; function Person() {

} var person = new Person(); ```

自己和原型的属性撞了,用自己的

  1. 利用原型特点和概念,可以提取共有属性

  2. 对象如何查看原型 —— > 隐式属性proto

xxx:隐式命名规则,系统命名 _xxx :私人的属性,提醒他人尽量别碰这个属性

js Person.prototype.name = 'abc'; function Person() { //var this = { // __proto__ : Person.prototype 存放队形的原型,将原型和自己连接到一起 //}; } var person = new Person(); person.name; //当对象没有这个属性时,就会在__proto__里找原型里是否有该属性

构造函数内部原理 1. 在函数体最前面隐式的加上this = {} 2. 执行this.xxx = xxx; 3. 隐式的返回this this不为空

js var this = { // __proto__ : Person.prototype (可以修改 ```js Person.prototype.name = 'sunny'; function Person () {

} var person = new Person(); Person.prototype = { name : 'cherry'; } //person.name : sunny; // //Person.prototype.name 是新加属性 //而 这种写法改了原型

var obj = {name : 'a'}; var obj1 = obj; obj = {name : 'b'}; //obj1.name = 'a'; //obj.name = 'b';

Person.prototype.name = 'sunny'; function Person () {

} Person.prototype = { name : 'cherry'; } var person = new Person();

//person.name : cherry; ```

  1. 对象如何查看对象的构造函数 —— > constructor (可以自己更改

原型的增删改查

```js Person.prototype.lastName = "Deng"; function Person (name) { this.name = name; } var person = new Person('xiaoming');

person.lastName = 'Zhang'; //只能在person的属性上改,会给它加一个属性lastName Person.prototype.lastName = 'Wang'; //可修改原型属性

//删除 delete Person.prototype.lastName;

// Person.prototype = { name : "BMW"; } ```

原型链

  1. 如何构成原型链

原型还有原型 原型链的连接点是proto 原型链的终端为Object.prototype

  1. 原型链上属性的增删改查

本人修改,后代无法更改

特例:修改 引用值可以修改 在这里插入图片描述

js son.num ++; //101 //son.num = son.num + 1; father.num //100

```js Person. prototype = { name : "a", sayName : function () { console.log (this.name) ; } } function Person ( ) {

}
var person = new Person() ;
person.sayName()    // a
// a.sayName( )
// sayName里面的this指向是,谁调用的这个方法,this就是指向谁

```

  1. 绝大多数对象的最终都会继承自Object.prototype Object.creat(null)无原型

  2. Object.create(原型) ```js //var obj = Object.create(原型) Person.prototype.name = 'sunny'; function Person() {

} var person = Object.create(Person.prototype); ```

Math.ceil()向上取整 Math.floor()向下取整 eg: js Math.ceil(123.234) ----> 124 Math.floor(123.99) ----> 123

Math.random()随机产生0-1之间的数 随机产生0-100之间的数 Math.floor(Math.random()*100); Math.random().toFixed(2)*100会有精度问题

  • 可正常计算的范围 : 小数点 前16位,后16位

call/apply

作用:改变this指向

区别:后面传的参数形式不同

call:需要把实参按照形参的个数传进去 apply:需要传一个arguments

还有一种改变this指向 :bind bind 会将改变this后的函数传递回来,不立即执行,在执行的时候传递参数

```js function test () {

}
test() ---->  test.call();


function Person (name,age) {
    //this == obj
    this.name = name;
    this.age = age;
}
var person = new Person('Deng',100);
var obj = {};

Person.call(obj,'Deng',100);    // 将Person里所有的this都改为obj,默认指向window

// obj :{name: "Deng", age: 100}

```

  • 使用call的对象必须是new出来的

```js function Person (name,age,sex) { this.name = name; this.age = age; this.sex = sex; }

function Student (name,age,sex,grade) {
    Person.call(this,name,age,sex);
    //Person.apply(this,[name,age,sex]);
    this.grade = grade;
}
var student = new Student('aaa',30,'male',6);

```

在这里插入图片描述

Guess you like

Origin blog.csdn.net/weixin_50945128/article/details/129377806