一、创建对象的方法
1、 {} 字面量创建
var person ={ name: "lisi", age: 21, say: function(){ alert(this.name); } };
2、 new Object()
var person = new Object(); person.name = "lisi"; person.age = 21; person.family = ["lida","lier","wangwu"]; person.say = function(){ alert(this.name); }
3: 用构造函数创建
function Person(name,age,family) { this.name = name; this.age = age; this.family = family; this.say = function(){ alert(this.name); } } var person1 = new Person("lisi",21,["lida","lier","wangwu"]); var person2 = new Person("lisi",21,["lida","lier","lisi"]); console.log(person1 instanceof Object); //true console.log(person1 instanceof Person); //true console.log(person2 instanceof Object); //true console.log(person2 instanceof Person); //trueconsole.log(person1.constructor); //constructor 属性返回对创建此对象的数组、函数的引用
4:Object.create方法创建
创建完的对象有2个特点
1、 可以添加属性 (属性的值为非函数的任意数据类型)
2、 添加方法
const person = { isHuman: false, say: function () { console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`); } }; const me = Object.create(person); //使用现有的对象来提供新创建的对象的__proto__
5、工厂模式
function createPerson(name,age,family) { var o = new Object(); o.name = name; o.age = age; o.family = family; o.say = function(){ alert(this.name); } return o; } var person1 = createPerson("lisi",21,["lida","lier","wangwu"]); //instanceof无法判断它是谁的实例,只能判断他是对象,构造函数都可以判断出 var person2 = createPerson("wangwu",18,["lida","lier","lisi"]);console.log(person1 instanceof Object); //true
6、原型模式
function Person() {} Person.prototype.name = "lisi"; Person.prototype.age = 21; Person.prototype.family = ["lida","lier","wangwu"]; Person.prototype.say = function(){ alert(this.name); }; console.log(Person.prototype); //Object{name: 'lisi', age: 21, family: Array[3]} var person1 = new Person(); //创建一个实例person1 console.log(person1.name); //lisi var person2 = new Person(); //创建实例person2 person2.name = "wangwu"; person2.family = ["lida","lier","lisi"];P9 console.log(person2); //Person {name: "wangwu", family: Array[3]} // console.log(person2.prototype.name); //报错 console.log(person2.age); //21
7、混合模式(构造函数模式+原型模式)
构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性 function Person(name,age,family){ this.name = name; this.age = age; this.family = family; } Person.prototype = { constructor: Person, //每个函数都有prototype属性,指向该函数原型对象,原型对象都有constructor属性,这是一个指向prototype属性所在函数的指针 say: function(){ alert(this.name); } } var person1 = new Person("lisi",21,["lida","lier","wangwu"]); console.log(person1); var person2 = new Person("wangwu",21,["lida","lier","lisi"]); console.log(person2);
new的工作原理
通过new创建对象经历4个步骤
1、创建一个新对象;[var o = {};] //创建一个空对象obj,然后把这个空对象的__proto__设置为Person.prototype(即构造函数的prototype);
2、将构造函数的作用域赋给新对象 (因此this指向了这个新对象);[Person.apply(o)] [Person原来的this指向的是window]
3、执行构造函数中的代码(为这个新对象添加属性);
4、返回新对象
什么是面向对象编程(OOP)?
面向过程与面向对象
1)面向过程:面向过程专注于如何去解决一个问题的过程步骤。编程特点是由一个个函数去实现每一步的过程步骤,没有类和对象的概念。
2)面向对象:专注于由哪一个对象来解决这个问题,编程特点是出现了一个类,从类中拿到对象,由这个对象去解决具体问题。 对于调用者来说,面向过程需要调用者自己去实现各种函数。而面向对象,只需要告诉调用者,对象中具体方法的功能,而不需要调用者了解方法中的实现细节。
面向对象的三大特征
面向对象的三大特征是继承、封装、多态。JS可以模拟实现继承和封装,但是无法模拟实现多态,所以我们说JS是一门基于对象的语言,而非是面向对象的语言。
1、封装
什么是Js封装,就是当你需要隐藏一些属性和方法是,就可以将这些属性和方法封装起来,然后通过一个外部可以调用的特定接口(也可以说是一个公共的方法)进行调用。
function Person(name, age, sex) { this.name = name; //共有变量 var age = age; //私有变量 var sex = sex; //私有变量 this.show = function () { console.log(age + "====" + sex); } }
var person = new Person('Sunshine', 18, '女'); console.log(person.age); // undefined console.log(person.name); // Sunshine console.log(person.show()); // 18====女
注:this指向的都是共有的属性和方法,而直接通过var声明的则属于私有变量(即外部不可访问变量),然后通过一个共有的show方法将私有的age和sex输出。当然show方法也要通过this声明才可以哟,否则的话show方法也是不可访问的。
类和对象
1、类:一类具有相同特征(属性)和行为(方法)的集合。
比如,人类具有身高、体重等属性,吃饭、大笑等行为,所以,我们可以把人划分为一类。
2、对象:从类中,拿出具有确定属性值和方法的个体。
比如,张三-->属性:身高180体重180 方法:说话-->我叫张三,身高180
3、类和对象的关系:
①类是抽象的,对象是具体的(类是对象的抽象化,对象是类的具体化)
②类是一个抽象的概念,只能说类有属性和方法,但是不能给属性赋具体的。比如,人类有姓名,但是不能说人类的姓名叫什么。
对象是一个具体的个例,是将类中的属性进行具体赋值而来的个体。
比如,张三是一个人类的个体。可以说张三的姓名叫张三。也就是张三对人类的每一个属性进行了具体的赋值,那么张三就是由人类产生的一个对象。
4、使用类和对象的步骤:
1)创建一个类(构造函数):类名必须使用大驼峰法则。即每个单词首字母都要大写
function 类名(属性1){ this.属性1=属性1; this.方法=function(){ //方法中要调用自身属性,必须使用this.属性 } }
2)通过类实例化(new)出一个对象。
var obj=new 类名(属性1的具体值); obj.属性; 调用属性 obj.方法; 调用方法
3)注意事项:
①通过类名,new出一个对象的过程,叫做"类的实例化"。
②类中的this,会在实例化的时候,指向新new出的对象。
所以,this.属性 this.方法实际上是将属性和方法绑定在即将new出的对象上面。
③在类中,要调用自身属性,必须使用this.属性名。如果直接使用变量名,则无法访问对应的属性。
function Person(name,age){ this.name=name; this.age=age; this.say=function(content){ //在类中,访问类自身的属性,必须使用this.属性调用。 alert("我叫"+this.name+",今年"+this.age+"岁,我说了一句话:"+content); } } var zhangsan=new Person("姐姐",18); zhangsan.say("你好呀");
④类名必须使用大驼峰法则,注意与普通函数区分。
面向对象的两个重要属性
1)constructor:返回当前对象的构造函数。
2)instanceof:检测一个对象是不是一个类的实例;
>>>lisi instanceof Person //true √ lisi是通过Person类new出的 >>>lisi instanceof Object //true √ 所有对象都是Object的实例 >>>Person instanceof Object //true √ 函数本身也是对象
成员属性、静态属性和私有属性
1、在构造函数中,使用this.属性声明。或者在实例化出对象以后,使用"对象.属性"追加的,都属于"成员属性或成员方法"。也叫"实例属性或实例方法"。
成员属性/方法,是属于由类new出的对象的。
需要使用"对象名.属性名"调用。
【静态属性与静态方法】
2、通过“类名.属性名”、“类名.方法名”声明的属性和方法,称为静态属性、静态方法。也叫类属性和类方法。
类属性/类方法,是属于类的(属于构造函数的)
通过"类名.属性名"调用。
3、成员属性是属于实例化出的对象的,只能使用对象调用。
静态属性是属于构造函数的,只能使用类名调用。
[私有属性和私有方法]
4、在构造函数中,使用var声明的变量称为私有属性;
在构造函数中,使用function声明的函数,称为私有方法;
function Person(){ var num=1;//私有属性 function func(){}//私有方法 }
私有属性和私有方法的作用域,只在构造函数内容有效。即只能在构造函数内部使用,在构造函数外部,无论使用对象名还是类名都无法调用。
JavaScript中的this指向详解
1、谁最终调用函数,this最终指向谁(记住!)
①this指向谁,不应考虑函数在哪声明,而应该考虑函数在哪调用!!!
②this指向的永远只可能是对象,而不可能是函数。
③this指向的对象,叫做函数的上下文context,也叫函数的调用者。
2、this指向的规律!!!(跟函数的调用方式息息相关,记住这点,相信你一定会分清this指向哒)
①通过函数名()调用的,this永远指向window
②通过对象.方法调用的,this指向这个对象。
③函数作为数组中的一个元素,用数组下标调用的,this指向这个数组
④函数作为window内置函数的回调函数使用,this指向window。 setInterval setTimeout 等。
⑤函数作为构造函数,使用new关键字调用,this指向新new出的对象。
var fullname = 'John Doe'; var obj = { fullname: 'Colin Ihrig', prop: { fullname: 'Aurelio De Rosa', getFullname: function () { return this.fullname; } } }; console.log(obj.prop.getFullname()); //Aurelio De Rosa // 函数的最终调用者 obj.prop var test = obj.prop.getFullname; console.log(test()); //John Doe // 函数的最终调用者 test() this-> window obj.func = obj.prop.getFullname; console.log(obj.func()); //Colin Ihrig // 函数最终调用者是obj var arr = [obj.prop.getFullname, 1, 2]; arr.fullname = "JiangHao"; //JiangHao console.log(arr[0]()); // 函数最终调用者数组
class 与构造函数的区别?
构造函数
function Circle (x, y, r, color) { this.x = x this.y = y this.r = r this.color = color } Circle.prototype.render = function () { ctx.beginPath() ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, true) ctx.fillStyle = this.color ctx.fill() } Circle.prototype.update = function () { this.x += 1 }
class
class Circle { constructor (x, y, r, color) { this.x = x this.y = y this.r = r this.color = color } render () { ctx.beginPath() ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, true) ctx.fillStyle = this.color ctx.fill() } update () { this.x += 1 } }