this关键字

this的值通常是由所在函数的执行环境决定,也就是说要看函数是如何被调用的;同一个函数每一次调用,this都可能指向不同的对象。

示例:

console.log(this) // window对象在全局作用域下,this指向全局对象。

var person = {
  firstName  : "li",
  lastName   : "xiaoming",
  myFunction : function() {
    return this;    
  }
};
console.log(person.myFunction()) // // this表示person对象


var o = {
    x: 1,
    y: 2,
    sayHello: function () {
        console.log(this.x); // => 1:读取实例对象属性x的值
        console.log(x); // => 报错:读取的是变量x
    }
};
o.sayHello();

作用域

  • 局部作用域

// 此处不能调用 carName 变量
function myFunction() {
    var carName = "Volvo";
    // 函数内可调用 carName 变量
}
  • 全局作用域
全局变量有 全局作用域: 网页中所有脚本和函数均可使用。 

var outVariable = "我是最外层变量"; //最外层变量
function outFun() { //最外层函数
    var inVariable = "内层变量";
    function innerFun() { //内层函数
        console.log(inVariable);
    }
    innerFun();
}
console.log(outVariable); //我是最外层变量
outFun(); //内层变量
console.log(inVariable); //inVariable is not defined
innerFun(); //innerFun is not defined
  • 作用域链
当函数嵌套时,内层函数只能在外层函数作用域内执行,在内层函数执行的过程中,若需要引人某个变量,
首先会在当前作用域中寻找,若未找到,则继续向上一- 层级的作用域中寻找,直到全局作用域。
我们称这种链式的查询关系为作用域链。

var a = 100
function F1() {
    var b = 200
    function F2() {
        var c = 300
        console.log(a) // 自由变量,顺作用域链向父作用域找
        console.log(b) // 自由变量,顺作用域链向父作用域找
        console.log(c) // 本作用域的变量
    }
    F2()
}
F1()





原型链

Image text

一、构造函数
构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写。
另外就是调用方式的不同,普通函数是直接调用,而构造函数需要使用new关键字来调用。

function Person(name, age, gender) {
    this.name = name
    this.age = age
    this.gender = gender
    this.sayName = function () {
        alert(this.name);
    }
}
var person = new Person("孙悟空", 18, "男");

console.log(person) ///当我们直接在页面中打印一个对象时,事件上是输出的对象的toString()方法的返回值

二、原型
每当定义一个函数数据类型(普通函数、类)时候,都会天生自带一个prototype属性,
这个属性指向函数的原型对象,并且这个属性是一个对象数据类型的值。

console.log(Person.prototype);

三、原型链
1.__proto__和constructor
每一个对象数据类型(普通的对象、实例、prototype......)也天生自带一个属性__proto__,
属性值是当前实例所属类的原型(prototype)。
原型对象中有一个属性constructor, 它指向函数对象。


console.log(person.__proto__ === Person.prototype)//true
console.log(Person.prototype.constructor===Person) //true


console.log(person.__proto__) // Person.prototype
console.log(person.__proto__.__proto__) // //Object
console.log(person.__proto__.__proto__.__proto__) // null

//所以person的原型链为
person -> Person.prototype -> Object -> null;


onsole.log(Person.prototype);
console.log(Person.prototype.__proto__); //Object
console.log(Person.prototype.__proto__.__proto__); //null

//所以Person的原型链为:

Person -> Person.prototype -> Object -> null;


  • proto、prototype、constructor 的关系
示例:

var o = {};

// true :对象的__proto__等于类的prototype
console.log(o.__proto__ === Object.prototype); 

// true :对象的constructor 等于 类
console.log(o.constructor === Object); 

// true :o.constructor.prototype 可表示对象的原型。
console.log(o.constructor.prototype === Object.prototype);
  • Object.assign()
// 基本用法
let target = {a: 1};
let object2 = {b: 2};
let object3 = {c: 3};
Object.assign(target,object2,object3);  
// 第一个参数是目标对象,后面的参数是源对象
console.log(target);  // {a: 1, b: 2, c: 3}

// 合并具有相同属性的对象
const o1 = { a: 1, b: 1, c: 1 };
const o2 = { b: 2, c: 2 };
const o3 = { c: 3 };

const obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }

//数组的处理
console.log(Object.assign([2,3], [5]));  // [5,3]
  • Object.is(value1, value2)
// 用来比较两个值是否严格相等
console.log(Object.is("q","q"));      // true
console.log(Object.is([1],[1]));      // false

//与(===)的区别
//一是+0不等于-0
console.log(Object.is(+0,-0));  //false
console.log(+0 === -0)  //true
//二是NaN等于本身
console.log(Object.is(NaN,NaN)); //true
console.log(NaN === NaN)  //false
  • Object.defineProperty()
// 直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

function Archiver() {
  var temperature = null;
  var archive = [];

  Object.defineProperty(this, 'temperature', {
    get: function() {
      console.log('get!');
      return temperature;
    },
    set: function(value) {
      temperature = value;
      archive.push({ val: temperature });
    }
  });

  this.getArchive = function() { return archive; };
}

var arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;
arc.temperature = 13;
console.log(arc.getArchive()) // [{ val: 11 }, { val: 13 }]
  • Object.keys(), Object.values()
// Object.keys(): 返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。
// Object.values(): 返回一个给定对象自身的所有可枚举属性值的数组.

// 简单数组
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2'];
console.log(Object.values(obj)); // ['bar', 42]

// 类数组对象
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']
console.log(Object.values(obj)); // ['a', 'b', 'c']

// 排序的类数组对象
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']
console.log(Object.values(an_obj)); // ['b', 'c', 'a']





  • JSON.stringify(object)

序列化对象;把对象转换成一个字符串。

示例:

var o = {
    x: 1,
    y: 2
}

JSON.stringify(o); // => {"x":1,"y":2}:返回一个字符串
  • JSON.parse(jsonStr)

将一个Json字符串转换为对象。

示例:

var str = '{ "x":1,"y":2 }'; // 字符串的属性名要用引号框起来
var o = JSON.parse(str);
console.log(o.x); // => 1:输出对象属性x的值

Set

对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用

  • 集合表示无重复值的有序列表;let set = new Set ();创建一个新的集合;
  • set.add();
  • set.delete()
  • 校验某个值是否在set中:set.has()
  const set1 = new Set([1, 2, 3, 3, 4, 5, 2]);
  console.log(set1) // Set(5) {1, 2, 3, 4, 5}
  let set2 = [...set1]
  console.log(set2) // (5) [1, 2, 3, 4, 5]

  var mySet = new Set();
  mySet.add(1);
  mySet.add(5).add("some text"); // 可以链式调用

  console.log(mySet);
  // Set [1, 5, "some text"]

  mySet.add(5).add(1);
  console.log(mySet);
  // Set [1, 5, "some text"]  // 重复的值没有被添加进去



  var mySet = new Set();
  mySet.add("foo");

  console.log(mySet.delete("bar")); // 返回 false,不包含 "bar" 这个元素
  console.log(mySet.delete("foo")); // 返回 true,删除成功


  var mySet = new Set();
  mySet.add('foo');
  console.log(mySet.has('foo'));  // 返回 true
  console.log(mySet.has('bar'));// 返回 false

  var set1 = new Set();
  var obj1 = {'key1': 1};
  set1.add(obj1);

  console.log(set1.has(obj1));      // 返回 true
  console.log(set1.has({'key1': 1}));  // 会返回 false,因为其是另一个对象的引用
  console.log(set1.add({'key1': 1})); // 现在 set1 中有2条(不同引用的)对象了


Map

Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值) 都可以作为一个键或一个值。

  • Map 对象。
  • Map 与数组的关系。

let myMap = new Map();

let keyObj = {};
let keyFunc = function() {};
let keyString = 'a string';

// 添加键
myMap.set(keyString, "和键'a string'关联的值");
myMap.set(keyObj, "和键keyObj关联的值");
myMap.set(keyFunc, "和键keyFunc关联的值");

myMap.size; // 3

// 读取值
myMap.get(keyString);    // "和键'a string'关联的值"
myMap.get(keyObj);       // "和键keyObj关联的值"
myMap.get(keyFunc);      // "和键keyFunc关联的值"

console.log(myMap.get('a string'));  // "和键'a string'关联的值"  
// 因为keyString === 'a string'
console.log(myMap.get({}))          // undefined, 因为keyObj !== {}
console.log(myMap.get(function() {})); // undefined, 因为keyFunc !== function () {}



let kvArray = [["key1", "value1"], ["key2", "value2"]];
// 使用常规的Map构造函数可以将一个二维键值对数组转换成一个Map对象
let myMap = new Map(kvArray);
// 使用Array.from函数可以将一个Map对象转换成一个二维键值对数组
console.log(Array.from(myMap)); // 输出和kvArray相同的数组
// 更简洁的方法来做如上同样的事情,使用展开运算符
console.log([...myMap]);


// Map对象同数组进行合并时,如果有重复的键值,则后面的会覆盖前面的。
let first = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);

let second = new Map([
  [1, 'uno'],
  [2, 'dos']
]);

let merged = new Map([...first, ...second, [1, 'eins']]);

console.log(merged); // Map(3) {1 => 'eins', 2 => 'dos', 3 => 'three'}
console.log(merged.get(1)); //eins
powered by GitbookEdit Time: 2023-04-08 10:28:32