JavaScript 基础知识

JS 基本数据类型

Undefined、Null、Boolean、String、Number

ES6 新增 Symbol,表示独一无二的值,凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突

Null 和 Undefined 的区别:

  • null:表示一个对象是“没有值”的值,即值为“空”;typeof 为 object

  • undefined:表示一个声明但没有初始化的变量;typeof 为 undefined

JS 的数据类型、及内存位置

栈:原始数据类型(Undefined、Null、Boolean、Number、String)

堆:引用数据类型(对象、数组、函数)

JS 内置对象

数据封装对象:Object、Array、Boolean、Number、String、Map、WeakMap、Set、WeakSet

其他对象:Function、Arguments、Math、Date、RegExp、Error

Object 是 JS 中所有对象的父对象

原型、原型链

每个对象都会在其内部初始化一个属性,就是 prototype (原型)

当我们访问一个对象的属性时, 如果这个对象内部不存在这个属性,那么他就会去 prototype 里找这个属性,这个prototype 又会有自己的 prototype , 于是就这样一直找下去,这样的一个链型结构就是原型链

let obj = Object.create(null)

这种方式创建的对象没有原型。使用的情景:

  • 你需要一个非常干净且高度可定制的对象当作数据字典的时候;

  • 想节省 hasOwnProperty 带来的一丢丢性能损失并且可以偷懒少些一点代码的时候

JS 创建对象的方式

工厂模式

function createPerson(name, age) {
  var o = new Object();
  o.name = name;
  o.age = age;
  o.sayName = function () {
    alert(this.name);
  }
  return 0;
}

var person = createPerson('OreChou', 23);

所创建的对象的原型都为 Object 。这种方式无法解决对象识别问题,即使用 instance 和 typeof 的时候,其值为 Object。

构造函数模式

// 此处的函数名首字母为大写,约定构造函数的首字母为大写
function Person(name, age) {
  this.name = name;
  this.age = age;
  // 方法会在每个实例上重新创建一遍
  this.sayName = function() {
    alert(this.name);
  }
  // 上面的代码与下面的等价
  // 相当于每次新建实例,都会创建一个函数,函数也是对象。所以有性能的开销
  this.sayAge = new Function("alert(this.age)");
}

var person = new Person('OreChou', 23);
person.constructor === Person // true
person instanceof Person // true

调用构造函数会经历以下步骤:

  • 以该函数为原型创建一个新对象

  • 将函数的 prototype 赋值给对象的 proto 属性

  • 将函数的作用域赋给新对象(即 this 指向了该新对象),执行函数中的代码

  • 若有 return(且不为基础类型)则返回 return 的内容,没有则返回新对象

缺点:

  • 每个方法都会在实例上重新创建一遍(解决:把这种方法改成全局的,或者使用原型)

构造函数 + 原型模式

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

Person.prototype = {
  // 这里指定了构造函数为 Person
  // 若不指定,则 Person 的原型为 Object
  constructor: Person,
  sayName: function() {
    alert(this.name);
  }
}

Person.prototype.sayAge = function() {
  alert(this.age);
}

var person = new Person('OreChou', 23);

Person.prototype.isPrototypeOf(person) // true

每一个函数都有一个 prototype 属性,属性为一个指针,指向一个对象。该对象可以包含该特定类型的所有实例共享的属性与方法。

构造函数的 prototype 属性,实例的 [[prototype]] 属性(Chrome、Safari、Firefox中每个实例对象上的属性 proto ),都指向函数的原型对象。

使用 Class

class Person {
  // 等价于 Person 的构造函数
  // 除 constructor 外没有其他方法的保留名
    constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  // 等价于 Person.prototype.sayName
  // 类中所有方法都是不可枚举的
  sayName() {
        console.log(this.name);
  }
}

// 上面和下面两种方法等价

let Person = (function() {
  'use strict';
  const Person = function(name, age) {
    if (typeof new.target === 'undefined') {
      throw new Error('必须通过关键字 new 调用函数');
    }
    this.name = name;
    this.age = age;
  }
  Object.defineProperty(Person.prototype, 'sayName', {
    value: function() {
      if (typeof new.target !== 'undefined') {
        throw new Error('不可以使用关键字 new 调用该方法');
      }
            console.log(this.name);
    },
    // 当且仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false。
    enumerable: false,
    // 当且仅当该属性的 writable 为 true 时,value 才能被赋值运算符改变。默认为 false。
    writable: true,
    // 当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false。
    configurable: true
  })
  return Person;
})

使用类的注意事项:

  • 类声明与 let 类似,不能被提升

  • 类中的所有代码自动运行在严格模式下

  • 类中所有方法都是不可枚举的

  • 类中有一个名为 constructor 的方法,且只能使用 new 调用,否则报错

  • 类中其他的方法不能使用 new 调用,否则报错

JS 实现继承的方式

假设有如下的一个 Animal 类

function Animal() {
  this.species = '动物'
}

构造函数继承

function Person(name, age) {
  // 使用call或apply方法,将父对象的构造函数绑定在子对象上
  Animal.apply(this, arguments);
  this.name = name;
  this.age = age;
}

原型继承

function Person(name, age) {
  this.name = name;
  this.age = age;
}
// (1)
// 将 Person 的原型对象指向 Animal 的实例 (这种方式因为新增了 Animal 的一个实例,所以消耗了内存)
// 此时的 Person.prototype.constructor 指向了 Person
Person.prototype = new Animal();
// 这样导致了继承链混乱,所以将 constructor 改回 Person
Person.prototype.constructor = Person;

// (2)
// 这种方式不会新增内存,但是对 Person 原型的修改会反应到 Aniaml 的原型上
Person.prototype = Animal.prototype

// (3)
// 利用空对象作为中介。F 是空对象,几乎不占据内存,且修改 Person 的原型,不会反应到 Animal 的原型上
var nullObj = function() {};
F.prototype = Animal.prototype;
Person.prototype = new F();
Person.prototype.constructor = Person;

拷贝继承

实现一个拷贝函数,将父对象的所有属性方法拷贝到子对象

// 浅拷贝的实现
function shallowCopy(p) {
  var c = {};
  for (var i in p) {
    // js 的对象是一个指针,指向了该对象在内存中的地址
    // 所以这里如果属性是一个对象的话,其实只拷贝了该对象的地址
    // 那么拷贝后的对象对该属性的修改,会影响到原对象
    c[i] = p[i];
  }
  return c;
}

// 深拷贝的一个简单实现
function deepCopy(p) {
  // 确定 p 为对象还是数组
  var c = Array.isArray(p) ? [] : {};
  if (p && typeof p === 'object') {
    for (var i in p) {
      // 如果属性是对象,则递归拷贝
      if (p[i] && typeof p[i] === 'object') {
          c[i] = deepCopy(p[i]);
      } else {
        c[i] = p[i];
      }
    }
  }
  return c;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容