JavaScript知识点

this指向问题

this是 JavaScript 语言的一个关键字。
它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用。

  • 情况一:纯粹的函数调用

这是函数的最通常用法,属于全局性调用,因此this就代表全局对象。请看下面这段代码,它的运行结果是1。

var x = 1;
function test() {
   console.log(this.x);
}
test();  // 1
  • 情况二:作为对象方法的调用

函数还可以作为某个对象的方法调用,这时this就指这个上级对象。

function test() {
  console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;

obj.m(); // 1

  • 情况三: 作为构造函数调用

所谓构造函数,就是通过这个函数,可以生成一个新对象。这时,this就指这个新对象。

function test() {
 this.x = 1;
}

var obj = new test();
obj.x // 1

运行结果为1。为了表明这时this不是全局对象,我们对代码做一些改变:

var x = 2;
function test() {
  this.x = 1;
}

var obj = new test();
x  // 2

运行结果为2,表明全局变量x的值根本没变。

  • 情况四: apply 调用

apply()是函数的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象。因此,这时this指的就是这第一个参数。

var x = 0;
function test() {
 console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;
obj.m.apply() // 0

apply()的参数为空时,默认调用全局对象。因此,这时的运行结果为0,证明this指的是全局对象。
如果把最后一行代码修改为

obj.m.apply(obj); //1

运行结果就变成了1,证明了这时this代表的是对象obj。

  • 情况五: 匿名函数自执行

因为函数执行时,实际是window调用了它,也就是window.函数名();那么,里面的this指向当前调用该函数的对象,就是window。

  • 情况六: 定时器中的this指向

如果没有特殊指向,setInterval和setTimeout的回调函数中this的指向都是window。这是因为JS的定时器方法是定义在window下的


作用域链

查找变量的过程。先找自己局部环境内部有没有声明或者是函数,如果有,则查看声明有无赋值或者是函数的内容,如果没有,则向上一级查找。


混入式继承的实现

它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”。
被继承的类称为“基类”、“父类”或“超类”。

//混入式继承(拷贝)
//obj2继承到obj1中的成员,可以直接将obj1中的成员拷贝到obj2中即可
var obj1 = {name:"zs",age:10};
var obj2 = {};
// 将obj1中的成员拷贝到obj2中
for (var key in obj1) {
obj2[key] = obj1[key];
}
console.log(obj1);
console.log(obj2);

混入式继承方式看似很简单,但是存在共享数据安全的问题。

var obj1 = {name:"zs",age:10,car:{name:"mini"}};
var obj2 = {};
// 将obj1中的成员拷贝到obj2中
for (var key in obj1) {
obj2[key] = obj1[key];
}
//修改obj1对象中的car属性
obj1.car.name = "bus";
console.log(obj1);
console.log(obj2);

当我们需要修改某些对象中的引用类型对象的时候,会造成其他相关的对象也被修改,这是我们不希望看到的。

原型式继承的实现

回想一下,当我们在访问一个对象中的成员的时候,首先是在当前对象中查找,如果找不到,就往上,
在原型链中依次查找,如果在整个原型链中也不存在该成员,那么就返回undefined。
所以,我们想要在A对象中访问到B对象中的成员,除了将B中的成员添加到A中,如:混入式,我们也可以考虑将B中成员添加到A的原型链中,实现对象成员的共享。

function Animal() {
}
Animal.prototype.name="animal";
function Person() {
}
//修改Person的原型对象
Person.prototype= Animal.prototype;
Person.prototype.useTool = function () {
console.log("use fire");
}
var p = new Person();
console.log(p);
var ani = new Animal();
console.log(ani);

这种方式实现的继承称之为原型继承,实现也是比较方便的,当时和混入式一样,存在数据共享的问题。

原型链继承的实现

这种方式存在问题是,只能继承父类对象原型上的成员,但无法继承父类对象中的成员。

function Animal() {
this.color="red";
}
Animal.prototype.weight=100;
function Person() {
}
Person.prototype = new Animal();
var p = new Person();
console.log(p.color);//red

使用原型链继承方式能够继承到更多的成员。但是依然存在问题:

  1. 共享的问题
  2. 无法向构造器传参

借用构造函数继承

function SubClass(color, name, age) {
//SuperClass.call(this,name,age);
SuperClass.apply(this,[name,age]);
this.color = color;
}

以上就是借用构造函数继承(也要对象冒充)的两种实现方式。当然,这种继承方式都存在下面两个问
题:

  1. 如果父子构造函数存在相同的成员,那么子构造函数会覆盖父构造函数中的成员
  2. 不能继承原型链中的成员

组合继承

function SubClass(color, name, age) {
//SuperClass.call(this,name,age);
SuperClass.apply(this,[name,age]);//继承构造函数中的成员
this.color = color;
}
SubClass.prototype = new SuperClass();//继承原型链上的成员

问题:组合继承的问题在于在子类中调用父类一次。会导致性能浪费。

寄生式组合继承

// Chinese.prototype = Person.prototype;
// 原型继承改造
//1.创建F构造函数,并且返回实例 new F();
function object(parentPro){
  var F = function () {}
  F.prototype = parentPro;
  return new F();
}
//2.将返回的实例作为子类的原型对象,同时修改子类原型对象的constructor指向子类。
function inhert(par,child) {
  var mid  = object(par.prototype);
  mid.constructor = child;
  child.prototype = mid;
}

function Chinese(skin,language,name,age){
  this.skin = skin;
  this.language = language;
  Person.call(this,name,age)
}
inhert(Person,Chinese);
var p1 = new Chinese('黄皮肤','中文','小白',18)
console.log(p1);
p1.say();

总结: ECMAScript 实现继承的方式不止一种。这是因为 JavaScript 中的继承机制并不是明确规定
的,而是通过模仿实现的。这意味着所有的继承细节并非完全由解释程序处理。作为开发者,你有权决
定最适用的继承方式。


Object.create方法的基本使用

//第一种使用方法创建一个空对象,这个空对象中连最基本的原型对象都没有的
Object.create(null)
//创建传递进来的对象,并设置该对象的原型对象为当前的参数
Object.create(obj)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容

  • JS基础 页面由三部分组成:html:超文本标记语言,负责页面结构css:层叠样式表,负责页面样式js:轻量级的脚...
    小贤笔记阅读 606评论 0 5
  • 第3章 基本概念 3.1 语法 3.2 关键字和保留字 3.3 变量 3.4 数据类型 5种简单数据类型:Unde...
    RickCole阅读 5,128评论 0 21
  •   面向对象(Object-Oriented,OO)的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意...
    霜天晓阅读 2,109评论 0 6
  • 前端基础知识梳理 JavaScript部分 1.AJAX请求数据的步骤是什么?传输的数据是用的暗文还是明文? 步骤...
    不吃鱼的猫_8e95阅读 565评论 0 0
  • 1.原型 构造函数 实例 原型(prototype):每当定义一个对象(函数也是对象)的时候,对象都会包含一些...
    池鱼_故渊阅读 612评论 0 11