IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> [JavaScript] 二.面向对象 (loading...) -> 正文阅读

[JavaScript知识库][JavaScript] 二.面向对象 (loading...)

目录

一.new 命令

作用: 执行构造函数,返回一个实例对象

若不使用new命令,直接调用构造函数会怎样?

补充:?

new命令简化的内部流程,

new.target属性

Object.creat()方法

二.this 关键字

设计目的:在函数体内部,指代函数当前的运行环境

>> this本质? <<

注意点

Ⅰ.避免多层 this

Ⅱ.避免数组处理方法中的 this

//Ⅲ.避免回调函数中的 this

>> ※绑定 this 的方法 <<

三.对象的继承

四.Object 对象的相关方法

五.严格模式


?典型的面向对象编程语言(比如 C++ 和 Java),都有“类”(class)这个概念。所谓“类”就是对象的模板,对象就是“类”的实例。但是,JavaScript 语言的对象体系,不是基于“类”的,而是基于构造函数(constructor)和原型链(prototype)

JavaScript 语言使用构造函数(constructor)作为对象的模板。所谓”构造函数”,就是专门用来生成实例对象的函数。它就是对象的模板,描述实例对象的基本结构。一个构造函数,可以生成多个实例对象,这些实例对象都有相同的结构。

构造函数的特点:

  1. 函数体内部使用了this关键字,代表了所要生成的对象实例
  2. 生成对象的时候,必须使用new命令

一.new 命令

作用: 执行构造函数,返回一个实例对象

var Vehicle = function () {
  this.price = 1000;
};

var v = new Vehicle();
v.price // 1000


new命令执行时,构造函数内部的this,就代表了新生成的实例对象

new命令本身就可以执行构造函数,所以后面的构造函数可以带括号,也可以不带括号,?但是为了表示这里是函数调用,推荐使用括号。

若不使用new命令,直接调用构造函数会怎样?

此时

  • 构造函数变成了普通函数,并不会生成实例对象
  • this代表了全局对象
var Vehicle = function (){
  this.price = 1000;
};

var v = Vehicle();
v // undefined
price // 1000 ,(全局变量)

原本this在最外层代码中便是全局对象,?即

?

补充:?

????????博客园 / ~_~ /?>>全局对象和this指针<<

????????以及阮一峰老师的文章?>>JavaScript 的 this 原理<<

  • 为了保证构造函数必须与new命令一起使用,一个解决办法是,构造函数内部使用严格模式,即第一行加上use strict。这样的话,一旦忘了使用new命令,直接调用构造函数就会报错。?
function Animal(age){
    'use strict';
    this._age = age;
};

var cat = Animal(); 
//Uncaught TypeError: Cannot set property '_age' of undefined
    at Animal

var dog = new Animal(22);
dog._age //22
  • 另一个解决办法,构造函数内部判断是否使用new命令,如果发现没有使用,则直接返回一个实例对象。?
function Animal(age){
    if(!(this instanceof Animal)){
        return new Animal(age);
    }
    this._age=age;
};

var cat = Animal(11); 
cat._age;//11

var dog = new Animal(22);
dog._age //22

new命令简化的内部流程,

可以用下面的代码表示

function _new(/* 构造函数 */ constructor, /* 构造函数参数 */ params) {
  // 将 arguments 对象转为数组
  var args = [].slice.call(arguments);
  // 取出构造函数
  var constructor = args.shift();
  // 创建一个空对象,继承构造函数的 prototype 属性
  var context = Object.create(constructor.prototype);
  // 执行构造函数
  var result = constructor.apply(context, args);
  // 如果返回结果是对象,就直接返回,否则返回 context 对象
  return (typeof result === 'object' && result != null) ? result : context;
}

// 实例
var actor = _new(Person, '张三', 28);

new.target属性

函数内部可以使用new.target属性。如果当前函数是new命令调用,new.target指向当前函数,否则为undefined,?使用这个属性,可以判断函数调用的时候,是否使用new命令。

function f() {
  if (!new.target) {
    throw new Error('请使用 new 命令调用!');
  }
  // ...
}

f() // Uncaught Error: 请使用 new 命令调用!

Object.creat()方法

构造函数作为模板,可以生成实例对象。但是,有时拿不到构造函数,只能拿到一个现有的对象。我们希望以这个现有的对象作为模板,生成新的实例对象,这时就可以使用Object.creat()方法

var catA = {
    name : 'mimi',
    age : 2,
    talk: function(){
        console.log('Miao~,my name is '+this.name+'\n');
    }
};

var catB = Object.create(catA);
catB.talk(); // Miao~,my name is mimi
catB.age //2

?对象catAcatB的模板,后者继承了前者的属性和方法

二.this 关键字

设计目的:在函数体内部,指代函数当前的运行环境

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

var x = 1;
var obj = {
  f: f,
  x: 2,
};

// 单独执行
f() // 1

// obj 环境执行
obj.f() // 2

JavaScript 支持运行环境动态切换,也就是说,this的指向是动态的,没有办法事先确定到底指向哪个对象

  • 由于对象的属性可以赋给另一个对象,所以属性所在的当前对象是可变的,即this的指向是可变的。
var A = {
  name: '张三',
  describe: function () {
    return '姓名:'+ this.name;
  }
};

var B = {
  name: '李四'
};

B.describe = A.describe;
B.describe()
// "姓名:李四"

如果this所在的方法不在对象的第一层,这时this只是指向当前一层的对象,而不会继承更上面的层。

var a = {
  p: 'Hello',
  b: {
    m: function() {
      console.log(this.p);
    }
  }
};

a.b.m() // undefined

上面代码中,a.b.m方法在a对象的第二层,该方法内部的this不是指向a,而是指向a.b,因为实际执行的是下面的代码。

var b = {
  m: function() {
   console.log(this.p);
  }
};

var a = {
  p: 'Hello',
  b: b
};

(a.b).m() // 等同于 b.m()

如果要达到预期效果,只有写成下面这样。

var a = {
  b: {
    m: function() {
      console.log(this.p);
    },
    p: 'Hello'
  }
};

如果这时将嵌套对象内部的方法赋值给一个变量,this依然会指向全局对象。

var a = {
  b: {
    m: function() {
      console.log(this.p);
    },
    p: 'Hello'
  }
};

var hello = a.b.m;
hello() // undefined

上面代码中,m是多层对象内部的一个方法。为求简便,将其赋值给hello变量,结果调用时,this指向了顶层对象。为了避免这个问题,可以只将m所在的对象赋值给hello,这样调用时,this的指向就不会变。

var hello = a.b;
hello.m() // Hello

>> this本质? <<

注意点

  • Ⅰ.避免多层 this

var o = {
  f1: function () {
    console.log(this);
    var f2 = function () {
      console.log(this);
    }();
  }
}

o.f1()
// Object
// Window

★实际执行的是下面的代码

var temp = function () {
  console.log(this);
};

var o = {
  f1: function () {
    console.log(this);
    var f2 = temp();
  }
}

①一个常见的解决方法是在第二层改用一个指向外层this的变量

var o = {
  f1: function() {
    console.log(this);
    var that = this;
    var f2 = function() {
      console.log(that);
    }();
  }
}

o.f1()
// Object
// Object

②JavaScript 提供了严格模式,也可以硬性避免这种问题。严格模式下,如果函数内部的this指向顶层对象,就会报错。

var counter = {
  count: 0
};
counter.inc = function () {
  'use strict';
  this.count++
};
var f = counter.inc;
f()
// TypeError: Cannot read property 'count' of undefined

上面代码中,inc方法通过'use strict'声明采用严格模式,这时内部的this一旦指向顶层对象,就会报错。

  • Ⅱ.避免数组处理方法中的 this

var o = {
  v: 'hello',
  p:['玛卡巴卡','唔西迪西'],
  f: function f() {
    this.p.forEach(function (item) {
      console.log(this.v + ' ' + item);
    });
  }
}

o.f()

>>undefined a1
>>undefined a2


解决方法👇👇👇 
-----------------------
法一:使用中间变量固定this
var o={
    v:'hello',
    p:['玛卡巴卡','唔西迪西'],
    f:function f(){
        var that=this;
        this.p.forEach(function(item){console.log(that.v+'  '+item)});
    }
}
o.f()

>>hello  玛卡巴卡
>>hello  唔西迪西

------------------------
法二:将this当作foreach方法的第二个参数,固定它的运行环境
var o = {
  v: 'hello',
  p:['玛卡巴卡','唔西迪西'],
  f: function f() {
    this.p.forEach(function (item) {
      console.log(this.v + ' ' + item);
    }, this);
  }
}

o.f()

>>hello  玛卡巴卡
>>hello  唔西迪西
  • //Ⅲ.避免回调函数中的 this

>> ※绑定 this 的方法 <<

(使用callapplybind这三个方法,来切换/固定this的指向。)

三.对象的继承

四.Object 对象的相关方法

五.严格模式

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-08 11:13:05  更:2021-08-08 11:15:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 11:41:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码