一、面向对象

1.1 this的指向问题

要看清楚最终的函数调用者是谁。

IIFE也被当做函数直接运行,IIFE的this都是window对象

函数的arguments是类数组对象,比如传入的第0项参数是函数,让它运行:arguments0,函数中的上下文是arguments对象。还要知道函数的length和arguments.length的区别。

1.2构造函数

当一个函数用new运算符调用时,此时这个函数叫“构造函数”(constructor)

构造函数四步走

创建一个新空对象

this绑定给这个空对象

执行语句

返回这个对象

new 出来的所有对象拥有相同属性群,所以可以把构造函数当做类,被new出来的对象都是这个函数的实例。

当构造函数里面有return语句时,注意:

1.如果是return基本类型值,无视这个return,还是返回秘密创建的对象

2.如果是return引用类型值,则不返回原来的对象,而是返回引用类型值

原型链的知识:

构造函数的prototype属性就是实例的__proto__属性。对于一个对象来说,__proto__这个属性叫做自己的原型对象,就是自己的原型链。这个原型链有查找功能,当obj.haha时,obj身上没有haha属性,此时会查找obj.__proto__身上有没有haha属性,并且会继续查找obj.proto.__proto__属性身上有没有haha属性……

二、原型链

++ Object.prototype是所有对象原型链的终点 ++

任何对象都有原型对象(proto),最终指向Object.prototype,但是Object.prototype很特殊,它的__proto__终点是null。

JS中,对象是对象、函数、数组、正则等是对象,所有引用类型值都是对象,它们都有__proto__属性。

甚至,xiaoming的__proto__也是一个对象,这个对象也有__proto__。

var obj = {}
console.log(obj.__proto__ === Object.prototype); //true

Object()是内置的构造函数,所有的对象,可以认为是Object new出来的

var obj = new Object();
obj.name = "小明";
obj.age = 12;
console.log(obj)
console.log(obj.__proto__ === Object.prototype);

“{}”对象的__proto__都指向Object.prototype,因为它都是Object new出来的。

function People(name,age){
this.name = name;
this.age = age;
}
var xiaoming = new People("小明",12);
console.log(xiaoming.__proto__ === People.prototype); //true
console.log(xiaoming.__proto__.__proto__ === Object.prototype); //true
console.log(xiaoming.__proto__.__proto__.__proto__);; //null

综上所述,xiaoming的原型People.prototype也有原型,小明完整的家谱:

Object.prototype是唯一一个没有__proto__的对象,其他所有对象、函数、数组、正则等都有__proto__

三、内置构造函数

JS内置了很多构造函数,它们也称为“基本类型值”、“引用类型值”的包装类。

3.1引用类型值的构造函数

引用类型值的构造函数:Object()、Function()、Array()、RegExp()

3.1.1 Object()函数

Object()是内置的构造函数,可以直接 new它,返回一个空对象,可以给这个空对象添加属性:

var obj = new Object();
obj.name = "小明";
obj.age = 12;
console.log(obj)
console.log(obj.__proto__ === Object.prototype);

等价于:

var obj = {
name:"小明",
age:12
}

3.1.2 Function()函数

所有function字面量都是它的实例

function sum(a,b){
alert(a+b);
}
sum(3,5);

等价于:

var sum = new Function("a","b","alert(a+b);alert('算完啦!')");
sum(4,5)

在new Function的时候,先罗列所有形参列表,最后一个参数是函数体,注意,参数都是字符串。

console.log(sum.__proto__ === Function.prototype)

++ 任何函数都是Function()构造函数的实例,Object也是Function的实例,Function自己也是自己的实例。Function自己new自己。 ++

console.log(Object.__proto__ === Function.prototype);   //true
console.log(Function.__proto__ === Function.prototype); //true

++ Function和Object的关系: ++

console.log(Function.prototype.__proto__ === Object.prototype);    // true
console.log(Function.__proto__.__proto__ === Object.prototype); // true
console.log(Function.__proto__.__proto__ === Object.__proto__.__proto__); // true
console.log(Function.__proto__ === Object.__proto__); // true

3.1.3 Array()函数

Array()是系统内置的数组构造函数,任何的数组都是Array() new出来的。

var arr = new Array();
arr[0] = 100;
arr[1] = 200;
arr[2] = 300;
console.log(arr);

等价于:

var arr = [100,200,300];

函数能填参数,表示数组长度,但数组还是空数组:

var arr = new Array(8);

常用的数组方法,都定义在Array.prototype身上。

var arr = [3,3,4,4];
console.log(arr.__proto__ === Array.prototype); //true
console.log(arr.__proto__.__proto__ === Object.prototype); //true

3.1.4 RegExp()函数

任何正则表达式RegExp()函数的实例。

var reg = /\d/g;
//等价于
var reg = new RegExp("d","g");
console.log(reg.__proto__ === RegExp.prototype); //true
console.log(reg.__proto__.__proto__ === Object.prototype); //true

3.2基本类型值“包装类”

【Number()、String()、Boolean()】

基本类型值的构造函数,被称为“包装类”。JS体系为了完整,所以就人为造出了这三个包装类,没有什么用。

3.2.1 Number()函数

用于创建数字对象:

var a = new Number(3);
console.log(a)
console.log(typeof a)



用内置构造函数创建数字的时候,得到一个对象,这对象的原始值属性是:

[[PrimitiveValue]]: 3  //这个属性不可被枚举。

它和字面量创建数字的区别:

var a = new Number(3);
var b = 3;
console.log(a == b); //true
console.log(a === b); //false

用Number()创建的对象,可以参与数学运算:

Number的实例是一个对象,但这个对象一旦参数运算,将变为普通Number类型

var a = new Number(3);
a = a * 3
console.log(a)
console.log(typeof a)



Number()也可以用来把各种值转换为数组(不能转就是NaN),不需要用new调用。

console.log(Number("12"));   //12
console.log(Number("12年")); //NaN
console.log(Number("")); //0
console.log(Number(false)); //0
console.log(Number(true)); //1
console.log(Number({})); //NaN
console.log(Number([])); //0
console.log(Number([1,2])); //NaN

任何需要转为数字的隐式转换,实际上就是在调用Number函数。

3.2.2 String()函数

var str = new String("我喜欢你");
console.log(str)



String()也可以用来转换:

console.log(String(123));   //"123"
console.log(String(true)); //"true"
console.log(String([])); //""
console.log(String([1,2,3])); //"1,2,3"
console.log(String(NaN)); //"NaN"
console.log(String({})); //"[Object Object]"

3.2.3 Boolean()函数

不管值是false还是true,都能通过if的验证,都是true。

var b = new Boolean(false);
console.log(b)
console.log(typeof b);
if(b){
alert("真的");
}

3.3内置构造函数之间的关系

就三句话,死记:

1、“{}”对象是被Object new出来的。所以它的__proto__就会指向Object.prototype。

2、任何函数都是Function new出来的实例,所以只要它是函数(构造函数也是函数),它的__proto__就会指向Function.prototype。

3、Function是所有构造函数的妈,它自己也是自己的妈。

小明不是Object new出来的,是People new的,它的__proto__指向People.prototype。

console.log(Object.__proto__.__proto__ === Object.prototype); //true
console.log(Function.__proto__.__proto__ === Object.prototype); //true
console.log(Object.__proto__ === Function.prototype); //true
console.log(Function.__proto__ === Function.prototype); //true
console.log(Array.__proto__ === Function.prototype); //true
console.log(RegExp.__proto__ === Function.prototype); //true
console.log(Number.__proto__ === Function.prototype); //true
console.log(String.__proto__ === Function.prototype); //true
console.log(Boolean.__proto__ === Function.prototype); //true

四、相关的方法、属性、运算符

4.1 hasOwnProperty()方法

返回布尔值(true/false),用来检测某属性、某方法是不是在自己身上。

function People(name){
this.name = name;
}
People.prototype.sayHello = function(){
alert("你好");
}
var xiaoming = new People("小明");
console.log(xiaoming.hasOwnProperty("name")); //true
console.log(xiaoming.hasOwnProperty("sayHello")); //false
console.log(xiaoming.hasOwnProperty("toString")); //false

4.2 in运算符

返回布尔值(true/false),in运算符可以检查某个对象有没有能力调用某属性、某方法,而不管这个属性或方法是否定义在自己身上,还是原型身上。

字符串 in 对象

function People(name){
this.name = name;
}
People.prototype.sayHello = function(){
alert("你好");
}
var xiaoming = new People("小明");
console.log("name" in xiaoming); //true
console.log("sayHello" in xiaoming); //true
console.log("toString" in xiaoming); //true

4.3 constructor属性

每一个函数的prototype对象都有一个constructor属性,指向构造函数。

function People(name){
this.name = name;
}
var xiaoming = new People("小明");
console.log(People.prototype)
console.log(People.prototype.constructor === People); //true
console.log(People.prototype.hasOwnProperty("constructor")); //true
console.log(xiaoming.constructor === People); //true
console.log(xiaoming.hasOwnProperty("constructor")); //false

4.4 instanceof运算符

返回布尔值,用来检查某个对象是不是某个函数的实例

o instanceof F

如果F.prototype在o的原型链上,返回true,否则返回false

function People(name){
this.name = name;
}
var xiaoming = new People("小明");
function Dog(){
}
console.log(xiaoming instanceof People); //true
console.log(xiaoming instanceof Object); //true
console.log(xiaoming instanceof Dog); //false

小题目:

console.log(Object instanceof Object); //true
console.log(Function instanceof Function); //true
console.log(Function instanceof Object); //true
console.log(Number instanceof Function); //true
console.log(Number instanceof Number); //false

我们发现object.prototype是所有对象原型链的终点,所以我敢说任何原型X一定true。

x instanceof Object
// Function的prototype出现在自己的__proto__线上,所以是true
console.log(Function instanceof Function); //true

五、练习题

5.1题目1

function A(){}
function B(){
return new A(); //返回了引用类型值
}
A.prototype = B(); //返回了一个A的实例1
B.prototype = new B();//返回了一个A的实例2
var a = new A(); //返回了一个A的实例,赋给a
var b = new B(); //返回了一个A的实例,赋给b console.log(a.__proto__ == b.__proto__);
console.log(a instanceof A); //true
console.log(a instanceof B); // false
console.log(b instanceof A); //true
console.log(b instanceof B); //false

5.2题目2

[].constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor === Function //true

六、继承

6.1什么是继承

计算机领域,关注两个类的关系,就是看属性群之间的关系。

比如:人类和狗狗类属性群,难免会有交集,但是不完全重合,此时可以认为两个类没有任何关系。



看看人和学生的属性群:



| 小学生肯定是人,人的属性学生全有,人能做的事情学生都能做。

l 但是反过来,小学生的属性和能力,人不一定有。

“学生”细化了、精分了、更具体了“人”。

“学生”的实例要比“人”的实例少。

“学生”一定是人,但“人”不一定是学生。

术语上,我们称“学生类”继承(extend)“人类”。人类叫“父类(超类)”,学生类叫“子类”。

A继承了B,此时要意识到:

A拥有B的所有属性和方法

A的属性群比B大

A丰富了B,A把B变得更具体,范围更小。

6.2 JavaScript实现继承

JavaScript实现两个类:People类,Student类,要求People类拥有的属性和方法,Student类的实例也要拥有People的属性和方法。Student还能丰富自己类的属性和方法,很简单,只要求巧妙设计原型链。

//人类
function People(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
People.prototype.sayHello = function(){
alert("你好,我是" + this.name);
}
People.prototype.sing = function(){
alert("都拉米发骚啦稀~~~");
}
// 学生类
function Student(name,age,sex,id,banji,socre){
People.apply(this, arguments)
// this.name = name;
// this.age = age;
// this.sex = sex;
this.id = id;
this.banji = banji;
this.socre = socre;
}
//下面这条语句可以实现继承
Student.prototype = new People();
Student.prototype.study = function(){
alert(this.name + "在学习!");
}
var xiaoming = new Student("小明",12,"男",100001,"初三一班", 100)
xiaoming.study();
xiaoming.sayHello();
xiaoming.sing();
注:People.apply(this, arguments)和Student.prototype = new People();要在Student.prototype.*** = function(){}之前

jQuery创始人John Resig写了一个小包,20多行代码,解决了JS继承恶心的问题。

https://johnresig.com/blog/simple-javascript-inheritance/

引包之后,这个包改变我们创建JS类的方式(和jQuery一样改变了写JS的方式)

//人类
var People = Class.extend({
init : function(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
},
sayHello:function(){
alert("你好,我是" + this.name);
},
sing:function(){
alert("都拉米发骚啦希~~~");
}
}) //学生类
var Student = People.extend({
init : function(name,age,sex,id,banji,socre){
this._super(name,age,sex); //继承父类的属性
// this.name = name;
// this.age = age;
// this.sex = sex;
this.id = id;
this.banji = banji;
this.socre = socre;
},
study :function(){
alert(this.name + "在学习!");
}
})
var xiaoming = new Student("小明",12,"男",100001,"初三一班", 100)
console.log(xiaoming)
xiaoming.study();
xiaoming.sing();

七、上升到面向对象

面向对象是一种编程思想,两个字就能概括:自治(自己管理自己),深入理解,就是封装。每个对象个体仅需要管理自己即可。

面向对象初学阶段,当你遇见大量的结构、功能、性质、什么都一样的对象的时候,立刻想到用面向对象技术。

现在要给大家一个思维定式,面向对象的时候怎么编程:

  思考初程序中有哪些类,在前期我们的业务仅仅只有一个类,后期类会有多个。

  每个类有哪些方法和属性,就是他们自己有什么功能

  每个类之间如何通信、交互数据、此时就要用到设计模式,比如中介者模式、发布订阅模式(观察者模式)。

  这个类怎么进行单元测试,如果保证自己这个类鲁棒,每个类都鲁棒了,整个程序就鲁棒。

我们之前的编程叫“面向过程”,现在是“面向对象”编程(OO)

7.1面向对象-红绿灯(案例)

考虑一个问题,页面上要制作一个效果:100个红绿灯,点击某一个红绿灯,从红灯变黄灯,再次点击从黄灯变绿灯,再次点击就绿灯变红灯...

有一个信号量,点击按钮之后,信号量变化0、1、2、0、1、2、0、1、2...然后让div的background-position进行变化,你要写100个信号量、100个盒子、100个事件。

页面上出现的东西就是红绿灯,而且它们拥有相同的样子、性质、功能,所以可以让红绿灯设计成为一个类。

每一个类负责什么:①状态量 ②DOM元素。

每个JS对象中有两个属性,一个是状态属性,另一个是DOM对象

简单的说,DOM对象现在成为JS对象的一个属性。

这个类有哪些属性?
  DOM属性
  颜色属性 哪些方法?
  初始化方法 init()
  换颜色方法 changeToColor()
  绑定事件方法 bindEvent()

第一步:DOM结构和CSS样式,确保放一个div元素能看见灯出来了。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Document</title>
<style type="text/css">
*{ margin: 0; padding: 0;}
div.honglvdeng{
position: relative;
width: 140px;
height: 328px;
background: url(./images/honglvdeng.jpg);
}
</style>
</head>
<body>
<div id="box">
<div class="honglvdeng"></div>
</div>
</body>
</html>
//第二步:创建红绿灯类
//new Honglvdeng()时,会执行构造函数中的语句
//所以在构造函数中创建一个DOM对象,然后让它上树
function Honglvdeng(){
//每一个类中有两个属性:状态量、DOM
this.dom = null;
//状态属性
this.state = 0;
//初始化方法
this.init();
//事件监听方法
this.bindEvent();
}
//为了程序美观,整洁,好更改和可插拔性高,方便维护,将DOM和上树语句都写在初始化方法中
Honglvdeng.prototype.init = function(){
//创建DOM
this.dom = document.createElement('div');
//给DOM添加类名
this.dom.className = 'honglvdeng';
//上树
document.getElementById("box").appendChild(this.dom);
} //第三步:添加事件监听
Honglvdeng.prototype.bindEvent = function(){
//备份this,因为事件监听里面的this表示dom元素本身
var self = this;
this.dom.onmouseenter = function(){
// 改变信号量
// self.state++;
// if(self.state > 2) self.state = 0
//判断简写
self.state = ++self.state % 3;
self.dom.style.backgroundPositionX = -155 * self.state +'px';
}
}
//第四步:实例化100个红绿灯
var count = 100;
while(count--){
new Honglvdeng();
}

文章转载于mufengsm

34、JavaScript面向对象(内置构造函数&相关方法|属性|运算符&继承&面向对象)的更多相关文章

  1. 前端笔记之JavaScript面向对象(二)内置构造函数&相关方法|属性|运算符&继承&面向对象

    一.复习 1.1复习上下文 函数的调用方式 上下文 fun() window obj.fun() obj box.onclick = fun box setInterval(fun,1000) set ...

  2. day34 反射、面向对象内置方法:如__str__、面向对象的软件开发

    Python之路,Day21 = 反射.面向对象内置方法:如__str__.面向对象的软件开发 几个内置查看的方法使用 .__base__ 查看类的继承结构.mro() 对象找属性的顺序存在里面 -- ...

  3. JavaScript 常用内置对象(字符串属性、Math对象、Array数组对象)

    1.字符串属性   <script>   var test_var = "I Iove you"; console.log(test_var.charAt(3)) // ...

  4. python面向对象内置方法关于属性篇

    1.关于__xxxattr__之__getattr__.__setattr__.__delattr__ 2.关于__xxxitem__之__getitem__.__setitem__.__delite ...

  5. Python--反射(重点)、面向对象内置方法:如__str__、面向对象的软件开发

    复习: Python3统一了类与类型 类的名称空间在定义阶段产生,看名称空间:类.__dict__ Python3特点:可以多继承 Python3都是新式类 继承意义:解决重复代码   组合:也是解决 ...

  6. js内置构造函数属性修改问题

    在学习js原型时遇到一个问题,Array,Object等内置构造函数部分属性无法修改,我猜测可能是因为浏览器实现的原因造成的. 1.修改name属性无效. <script type=" ...

  7. python面向对象的基础语法(dir内置函数、self参数、初始化方法、内置方法和属性)

    面相对象基础语法 目标 dir 内置函数 定义简单的类(只包含方法) 方法中的 self 参数 初始化方法 内置方法和属性 01. dir 内置函数(知道) 在 Python 中 对象几乎是无所不在的 ...

  8. 第一百零八节,JavaScript,内置对象,Global对象字符串编码解码,Math对象数学公式

    JavaScript,内置对象,Global对象字符串编码解码,Math对象数学公式 学习要点: 1.Global对象 2.Math对象 ECMA-262对内置对象的定义是:"由ECMASc ...

  9. 一、JavaScript概述 二、JavaScript的语法 三、JavaScript的内置对象

    一.JavaScript的概述###<1>JavaScript的概念 又称ECMAScript,和java没有任何关系 嵌入在HTML元素中的 被浏览器解释运行的 一种脚本语言. ###& ...

随机推荐

  1. linux常用操作记录

    vim:多行注释 vim中多行注释和多行删除命令,这些命令也是经常用到的一些小技巧,可以大大提高工作效率.   多行注释:   1. 首先按esc进入命令行模式下,按下Ctrl + v,进入列(也叫区 ...

  2. Linux 安装 MySQL 详解(rpm 包)

    说明:Linux 系统中软件的安装在 root 用户下进行,此安装方式为 rpm 包方式,安装的版本为:MySQL-5.6.25-1.linux_glibc2.5.x86_64.rpm-bundle. ...

  3. PHP上传文件到七牛(Qiniu)

    上传文件到七牛最简单的方式就是使用七牛官方最新的SDK 安装PHP SDK composer require qiniu/php-sdk 上传文件到七牛 use Qiniu\Auth; use Qin ...

  4. const int * 和 int * const 傻傻分不清楚

    const int * a和int const *a一样,定义时不是必须初始化,指针可以指向其他变量,但是指向的变量的值不能修改. int * const定义时必须初始化,即必须指明指向哪个变量,定义 ...

  5. 常州模拟赛d5t3 appoint

    分析:这道题比较奇葩.因为字符串没有swap函数,所以一个一个字符串交换只有30分.但是我们可以不用直接交换字符串,而是交换字符串的指针,相当于当前位置是哪一个字符串,每次交换int,可以拿60分. ...

  6. 关于Git的简单使用

    新电脑git push一直出问题,到现在也没有解决,但是一些git的命令还是有用的,就先记下来吧.(下图就是没解决的报错) 一.上传本地项目到git 1.初始化git git init 2.配置用户名 ...

  7. Spring——ClassPathXmlApplicationContext(配置文件路径解析 1)

    ClassPathXmlApplicationContext     在我的 BeanFactory 容器文章中主要提及了 BeanFactory 容器初始化(Spring 配置文件加载(还没解析)) ...

  8. SiteMesh2-sitemesh.xml的PageDecoratorMapper映射器的用法

    继上一章http://www.cnblogs.com/EasonJim/p/7083165.html中使用的例子中,是通过decorators.xml文件通过URL匹配进行转换的. 而下面这种方法是通 ...

  9. memory management in oracle 11G R2

    When we talking about memory management in Oracle, we are refering to SGA and PGA. The management me ...

  10. ORACLE EM的删除与创建

    手动删除ORACLE 10G EM 使用emca可以手动配置em! 配置em的过程中有一个环节要特别主要: 不论使用dbca还是使用emca -deconfig dbcontrol db -repos ...