什么是对象

   对象是单个实物的抽象,通常需要一个模板,表示某一类实物的共同特征,然后对象根据这个模板生成。
对象是一个容器,封装了属性(property)和方法(method),属性是对象的状态,方法是对象的行为(完成某种任务)。
比如,我们可以把动物抽象为animal对象,使用“属性”记录具体是那一种动物,使用“方法”表示动物的某种行为(奔跑、捕猎、休息等等)。

面向对象编程的第一步,就是要生成对象。

典型的面向对象编程语言(比如 C++ 和 Java),都有“类”(class)这个概念。所谓“类”就是对象的模板,对象就是“类”的实例。

JavaScript 语言的对象体系,不是基于“类”的,而是基于构造数`constructor`和原型链`prototype`, 所以JS  专门使用构造函数作为对象模板  ,一个构造函数,可生成多个实列对象,它们有相同的结构

构造函数与普通函数区别

- 构造函数就是一个普通的函数,但是有自己的特征和用法。
- 函数体内部使用了this关键字,代表了所要生成的对象实例。
- 生成对象的时候,必须使用new命令。
//constructor
var Bird = function () {
  this.name = 'lai fu';
};
var bird1 = new Bird(); // 也可以使用 new Bird; 推荐使用前者
console.log(bird1.name) // "lai fu" //ordinary
var a =Bird();
console.log(a) // undefined
console.log(a.name) // typeError
name // 'laifu'

防止把构造函数`constructor`当普通函数使用

//使用 严格模式
function Fubar(foo, bar){
'use strict';
this._foo = foo;
this._bar = bar;
}
Fubar()// TypeError
//判断 this 不是构造函数(constructor)的实列对象 那么手动返回自身constructor function Far(a){
if (!(this instanceof Far)) return new Far(a); this._a=a;
}
Far(1)._a

`new`命令的原理

- 创建一个空对象,作为将要返回的对象实例。
- 将这个空对象的原型,指向构造函数的prototype属性。
- 将这个空对象赋值给函数内部的this关键字。
- 开始执行构造函数内部的代码。
/**
*新生成一个空对象
*链接到原型
*绑定 this
*返回新对象
**/
function _new(constuctor,param) {   // 获得构造函数
  let Con = [].shift.call(arguments);
  // 链接到原型
  let obj = Object.create(Con.prototype);
  // 绑定 this,执行构造函数
  let result = Con.apply(obj, arguments)
  // 确保 new 出来的是个对象
  return (typeof(result) === 'object' && result != null) ? result : obj
}
var fn = _new(
  function Person (name,age){
  this.name = name; this.age = age
  }, 'Owen', 28);
fn.name // 'Owen'

new.target

function f() {
console.log(new.target === f);
} f() // false
new f() // true
//可利用 它来判断是否使用 new 命令 function f() {
if (!new.target) {
throw new Error('请使用 new 命令调用!');
}
f() // Uncaught Error: 请使用 new 命令调用!

`this`实质

-  原始的对象以字典结构保存,每一个属性名都对应一个属性描述对象。

JavaScript 存储变量实际上是以下面的形式保存的。
var obj = { name: "Owen" };
{
name: {
[[value]]: "Owen" //函数的地址
[[writable]]: true //是否可赋值
[[enumerable]]: true//是否可枚举
[[configurable]]: true//是否可配置
}
}
//属性的值保存在属性描述对象的value属性里面。

  
如果 a 属性的值是 引用值  那么属性将以下面的形式保存的:

var obj = { fn: function () {} };
/*
{
fn: {
[[value]]:
[[writable]]: true
[[enumerable]]: true
[[configurable]]: true
}
}
*/
由于函数是一个单独的值,所以它可以在不同的环境(上下文)执行。
var f n= function () {};
var obj = { f: fn }; // 单独执行
fn() // obj 环境执行
obj.f()
 JavaScript 允许在函数体内部,引用当前环境的其他变量。
由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。
所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。
 
下面这几种用法,都会改变this的指向。
(obj.fn = obj.fn)() // window
// 等同于
(function () {
console.log(this);
})() (false || obj.fn)() // window
// 等同于
(false || function () {
console.log(this);
})() (4, obj.fn)() // window
// 等同于
(4, function () {
console.log(this);
})()
数组调用forEach 方法时函数内部this 指向window ,将父级上下文传递给forEach 改变this指向

var o = {
v: 'hello',
p: [ 'Owen', 18 ],
f: function f() {
this.p.forEach(function (item) {
console.log(this.v + '-' + item);
}, this); //将外层的this传递给forEach方法
}
} o.f() // hello-Owen hello-18

JavaScript 原型链 OOP(二)

end

JavaScript new 操作符 OOP(一)的更多相关文章

  1. JavaScript 原型链 OOP(二)

    原型对象 `prototype` -  原型对象的所有属性和方法,都能被实例对象共享;   JavaScript 通过构造函数生成新对象,因此构造函数可以视为对象的模板.实例对象的属性和方法,可以定义 ...

  2. 从头开始学JavaScript (五)——操作符(二)

    原文:从头开始学JavaScript (五)--操作符(二) 一.乘性操作符 1.乘法:*      乘法操作符的一些特殊规则: 如果操作数都是数值,按照常规的乘法计算,如果乘积超过了ECMAscri ...

  3. 从头开始学JavaScript (四)——操作符

    原文:从头开始学JavaScript (四)--操作符 一.一元操作符 1.自增自减操作符:分为前置型和后置型: 前置型:++a;--a; 后置型:a++;a--; 例: <script typ ...

  4. 坑:JavaScript 中 操作符“==” 和“===” 的区别

    标题:JavaScript 中 操作符"==" 和"===" 的区别 记录一些很坑的区别: 1. '' == '0' // false 0 == '' // t ...

  5. JavaScript中+操作符的特殊性

    在JavaScript中+操作符有两个作用: (1)加法运算 (2)字符串连接 在使用+操作符进行运算时,当+操作符两边都是数值类型的时候,进行加法运算; 当+操作符两边有任意一边是字符串,则进行字符 ...

  6. JavaScript 逗号操作符

    让我们从一个有趣的微博开始吧. 末尾的c是优先级最低的逗号操作符.逗号操作符是操作符优先级的最后一行,并且很少有文章记录,它隐藏着它的锋芒.它可能不是JavaScript强势操作符,但是我喜欢它.它简 ...

  7. JavaScript剩余操作符Rest Operator

    本文适合JavaScript初学者阅读 剩余操作符 之前这篇文章JavaScript展开操作符(Spread operator)介绍讲解过展开操作符.剩余操作符和展开操作符的表示方式一样,都是三个点 ...

  8. 细说javascript typeof操作符

    细说javascript typeof操作符 typeof定义 typeof是一元运算符,用来返回操作数类型的字符串.下面是ECAMScript5.1关于typeof的标准定义: NOTE:上面表格标 ...

  9. 初识JavaScript 变量, 操作符, 数组

    这里讲的不会太多, 因为所有的语言都是一样的, 一些基本的东西, 所以就随便写写. 变量 变量就是可变的量, 编程角度理解就是用于存储某种/某些数值的存储器. 我们可以把变量具象理解为一个盒子, 而我 ...

随机推荐

  1. 洛谷P4360 [CEOI2004]锯木厂选址(斜率优化)

    传送门 我可能根本就没有学过斜率优化…… 我们设$dis[i]$表示第$i$棵树到山脚的距离,$sum[i]$表示$w$的前缀和,$tot$表示所有树运到山脚所需要的花费,$dp[i]$表示将第二个锯 ...

  2. luogu4088 [USACO18FEB]Slingshot

    link 这题在线得写树套树,所以我写的离线+树状数组 对于每个询问,Ans=\(\max_{j=1}^n{|a_j-x_i|+|b_j-y_i|+t_i}\) 拆成四种情况 \(x_i\le a_j ...

  3. 选课 ( dp 树形dp 动态规划 树规)

    和某篇随笔重了?!!?!?!?!?!?不管了留着吧 题目: 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之 ...

  4. [转载]sscanf函数

    来源:http://c.biancheng.net/cpp/html/296.html 头文件:#include <stdio.h> sscanf()函数用于从字符串中读取指定格式的数据, ...

  5. Qt 学习之路 2(18):事件

    Home / Qt 学习之路 2 / Qt 学习之路 2(18):事件 Qt 学习之路 2(18):事件  豆子  2012年9月27日  Qt 学习之路 2  60条评论 事件(event)是由系统 ...

  6. 分页插件PageHelper

    一.PageHelper说明 如果你也在用Mybatis,建议尝试该分页插件,这个一定是最方便使用的分页插件. 该插件目前支持Oracle,Mysql,MariaDB,SQLite,Hsqldb,Po ...

  7. HDU2665(可持久化线段树板子)

    1.题意有坑,实际要求第k小. 2.没学过动态开点也没学过主席树,看一下博主思路然后妄想自己实现的后果就是拿命去调bug. const int maxn = 1e5 + 5; int test, n, ...

  8. JDK Throwable

    Throwable 1. 使用大量数组和List常量: private static final StackTraceElement[] UNASSIGNED_STACK = new StackTra ...

  9. 配置中心:Nacos, Apollo, Consul, Etcd

    Nacos, Apollo, Consul, Etcd 服务.应用不同粒度的配置更丰富的路由规则集中式管理的动态参数规则

  10. thinkPHP5.0使用form表单提交数据和删除文章,不用TP的提示页面,使用弹出提示信息

    form表单提交数据和删除文章时,TP的默认信息提示页面的看起来不是很好看,想要实现弹窗提示怎么做呢? 前端:可以使用前端的一个知识--iframe,iframe元素会创建包含另外一个文档的内联框架: ...