Skip to content

Commit

Permalink
新增和修改文章
Browse files Browse the repository at this point in the history
  • Loading branch information
hr1201 committed Aug 4, 2024
1 parent 955d358 commit 6fbe1a1
Show file tree
Hide file tree
Showing 9 changed files with 420 additions and 44 deletions.
101 changes: 101 additions & 0 deletions Rarrot/articles/JavaScript/new操作符.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# new操作符

new操作符会进行四步:
1. 创建一个空对象
2. 把空对象和构造函数的prototype关联起来
3. 把构造函数的this绑定到空对象上
4. 根据构造函数的返回值类型返回结果,如果是值类型就返回空对象,如果是引用类型就返回引用类型

```JavaScript
function newFn(Fun, ...args) {
// 1. 创建一个空对象
let obj = {};
// 2. 把空对象和构造函数的prototype关联起来
obj.__proto__ = Fun.prototype;
// 3. 把构造函数的this绑定到空对象上
const result = Fun.apply(obj,args)
// 4. 根据构造函数的返回值类型返回结果,如果是值类型就返回空对象,如果是引用类型就返回引用类型
return result instanceof Object ? result : obj;
}

function person(name) {
this.name = name;
}

person.prototype.say = () => {
console.log('说话');
};

let obj = newFn(person, "Rarrot");
obj.say(); // 说话
console.log(obj) // person {name: 'Rarrot'}
```

## 注意

1. 引用类型之间通过new操作符创建的对象是不相等的,例如:

```JavaScript
function Person() {
this.name = 'Rarrot';
}

let person1 = new Person();
let person2 = new Person();

console.log(person1 === person2); // false
console.log([ 1 ] === [ 1 ]); // false
```

2. 对象的key都是**字符串**,如果是引用类型也会自动转换为字符串,例如:

```JavaScript
let obj = {};
let arr1 = { a: 1 };
let arr2 = { b: 2 };
obj[arr1] = 1;
obj[arr2] = 2;// arr1.toString() === arr2.toString(),所以会覆盖掉arr1
for (let key in obj) {
console.log(key + ':' + obj[key]); // [object Object]:2
}
```

3. 对象找属性|方法的顺序:

在对象本身找 ==> 在构造函数上找 ==> 在对象原型上找 ==> 构造函数原型上找 ==> 对象上一级找 ==> Object.prototype

```JavaScript
function Person() {
this.name = 'Rarrot';
this.age = 777; // 在构造函数中添加
}
Person.prototype.age = '999'; // 在构造函数原型上添加
let person = new Person();
person.age = '666'; // 在对象本身添加
person.__proto__.age = '888'; // 在对象原型上添加
Object.prototype.age = '000'; // 在Object上添加
console.log(person.age); // 666
console.log(person.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null
```

## object

为什么在Object 参考页,会发现左侧列出许多属性和方法——大大超过我们在自己定义的对象中看到的继承成员的数量。

原因在于,继承的属性和方法是定义在 prototype 属性之上的(你可以称之为子命名空间 (sub namespace) )——那些以 Object.prototype. 开头的属性,而非仅仅以 Object. 开头的属性。

prototype 属性的值是一个对象,我们希望被原型链下游的对象继承的属性和方法,都被储存在其中,而不希望被继承的则放于Object自身,记住每一个对象都有一个原型(prototype)属性,其指向另一个对象。由下图可以看出,prototype内部存在有许多的属性和方法,原因即为以上所述

![](https://cdn.jsdelivr.net/gh/hr1201/img@main/imgs/202402291750719.png)

于是 Object.prototype.watch()、[Object.prototype.valueOf()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf) 等等成员,适用于任何继承自 Object() 的对象类型,包括使用构造器创建的新的对象实例。

[Object.is()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/is)、[Object.keys()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/keys),以及其他不在 prototype 对象内的成员,不会被“对象实例”或“继承自 Object() 的对象类型”所继承。这些方法/属性仅能被 Object() 构造器自身使用。
File renamed without changes.
115 changes: 115 additions & 0 deletions Rarrot/articles/JavaScript/作用域.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# 作用域

1. **全局作用域**:全局作用域是最外围的作用域,根据 ECMAScript 的定义,全局作用域在网页中任何地方都能访问到。

2. **函数作用域**:函数作用域是在函数内部声明的变量只能在函数内部访问。

3. **块级作用域**:块级作用域是在代码块内部声明的变量只能在该代码块内部访问。


## 全局作用域

全局作用域是最外围的作用域,根据 ECMAScript 的定义,全局作用域在网页中任何地方都能访问到。

```javascript
var a = 1;
console.log(a); // 1
```

## 函数作用域

函数作用域是在函数内部声明的变量只能在函数内部访问。

```javascript
function foo() {
var a = 1;
console.log(a); // 1
}

foo();
console.log(a); // Uncaught ReferenceError: a is not defined
```

## 块级作用域

块级作用域是在代码块内部声明的变量只能在该代码块内部访问。

```javascript
console.log(a); // undefined,变量提升

if (true) {
var a = 1;
console.log(a); // 1

let b = 2;
console.log(b); // 2
}

console.log(a); // 1
console.log(b); // Uncaught ReferenceError: b is not defined
```

## 作用域链

作用域链是一个指向变量对象的指针列表,它保证了变量的有序访问。内部可以访问外部的变量,但是外部不能访问内部的变量。

注意:如果内部变量和外部变量同名,内部变量会覆盖外部变量。

```javascript
var a = 1;

function foo() {
var b = 2;

function bar() {
var c = 3;
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
}

bar();
}

foo();
```

## 优先级

声明变量 > 声明普通函数 > 参数 > 变量提升

```javascript
function foo() {
// var a = 1; // 声明a变量

console.log(a); // ƒ a() {},如果前面有声明a变量,则输出声明变量的值

var a = 2; // 变量提升

// 普通声明函数是不看写函数时的位置的,只看函数声明的位置
function a() {}
}

foo();
```

## 注意

注意声明变量时不使用`var`关键字,会自动提升到全局作用域。

```javascript
(function () {
var a = b = 10;

/*
* 等价于
* b = 10; // 全局作用域
* var a = b;
*/
})()

console.log(b); // 10

console.log(a); // Uncaught ReferenceError: a is not defined
```

98 changes: 98 additions & 0 deletions Rarrot/articles/JavaScript/数组.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# 数组

## 判断数组

```js
// 1. isArray
const arr = [1, 2, 3]
console.log(Array.isArray(arr)) // true

// 2. instanceof
console.log(arr instanceof Array) // true

// 3. constructor
console.log(arr.constructor === Array) // true

// 4. Object.prototype.toString.call()
console.log(Object.prototype.toString.call(arr).indexOf('Array') !== -1) // true

// 5. Array.prototype.isPrototypeOf()
console.log(Array.prototype.isPrototypeOf(arr)) // true
```

## slice和splice

`slice``splice`都是数组的方法,但是它们的作用不同。

- `slice`:返回一个新的数组,包含从开始到结束(不包括结束)的元素,原数组不会被修改。

```js
const arr = [1, 2, 3, 4, 5]
const newArr = arr.slice(1, 3)
console.log(newArr) // [2, 3]
console.log(arr) // [1, 2, 3, 4, 5]
```

- `splice`:从数组中添加或删除元素,返回被删除的元素,原数组会被修改。

```js
const arr = [1, 2, 3, 4, 5]
const newArr = arr.splice(1, 3)
console.log(newArr) // [2, 3, 4]
console.log(arr) // [1, 5]
```

## 数组去重

### 1. Set

```js
const arr = [1, 2, 3, 4, 5, 1, 2, 3]
const newArr = [...new Set(arr)]
console.log(newArr) // [1, 2, 3, 4, 5]
```

### 2. filter

```js
const arr = [1, 2, 3, 4, 5, 1, 2, 3]
const newArr = arr.filter((item, index) => arr.indexOf(item) === index)
console.log(newArr) // [1, 2, 3, 4, 5]
```

### 3. reduce

```js
const arr = [1, 2, 3, 4, 5, 1, 2, 3]
const newArr = arr.reduce((prev, cur) => prev.includes(cur) ? prev : [...prev, cur], [])
console.log(newArr) // [1, 2, 3, 4, 5]
```

## 数组扁平化

### 1. flat

```js
const arr = [1, [2, 3], [4, [5, 6]]]
const newArr = arr.flat(Infinity)
console.log(newArr) // [1, 2, 3, 4, 5, 6]
```

### 2. reduce

```js
const arr = [1, [2, 3], [4, [5, 6]]]
const flatten = arr => arr.reduce((prev, cur) => prev.concat(Array.isArray(cur) ? flatten(cur) : cur), [])
const newArr = flatten(arr)
console.log(newArr) // [1, 2, 3, 4, 5, 6]
```

## 数组乱序

```js
const arr = [1, 2, 3, 4, 5]
const newArr = arr.sort(() => Math.random() - 0.5)
console.log(newArr)
```


32 changes: 0 additions & 32 deletions Rarrot/articles/JavaScript/问题/new操作符.md

This file was deleted.

12 changes: 0 additions & 12 deletions Rarrot/articles/JavaScript/问题/object.md

This file was deleted.

Loading

0 comments on commit 6fbe1a1

Please sign in to comment.