js_面向对象_new关键字_对象与this_ES6种对象相关的特性实例
文章目录
字面量对象
重新介绍 JavaScript(JS 教程) - JavaScript | MDN (mozilla.org)
- 对象作为函数参数:
在经典的面向对象语言中,对象是指数据和在这些数据上进行的操作的集合。与 C++ 和 Java 不同,JavaScript 是一种基于原型的编程语言,并没有 class 语句,而是把函数用作类。那么让我们来定义一个人名对象,这个对象包括人的姓和名两个域(field)。名字的表示有两种方法:“名 姓(First Last)”或“姓, 名(Last, First)”。使用我们前面讨论过的函数和对象概念,可以像这样完成定义:
function makePerson(first, last) { return { first: first, last: last }; } function personFullName(person) { return person.first + ' ' + person.last; } function personFullNameReversed(person) { return person.last + ', ' + person.first; } var s = makePerson('Simon', 'Willison'); personFullName(s); // "Simon Willison" personFullNameReversed(s); // "Willison, Simon"
利用返回对象的函数创建对象
function makePerson(first, last) { return { first: first, last: last }; }
利用关键字new调用构造函数(constructor)来得到(或者说constructor修改一个空对象)得到想要的对象
利用原型链修改对象模板中的属性/方法
function Person(first, last) { this.first = first; this.last = last; } Person.prototype.fullName = function() { return this.first + ' ' + this.last; } Person.prototype.fullNameReversed = function() { return this.last + ', ' + this.first; }
原型对象
Person.prototype
是一个可以被 Person
的所有实例共享的对象。
它是一个名叫 原型链
(prototype chain)的 查询链
的一部分:当你试图访问 Person<span>
某个实例(例如上个例子中的s)一个没有定义的属性时,解释器会首先检查这个 Person.prototype
来判断是否存在这样一个属性。
所以,任何分配给 Person.prototype
的东西对通过 this
对象构造的实例都是可用的。
这个特性功能十分强大,JavaScript 允许你在程序中的任何时候修改原型(prototype)中的一些东西,也就是说你可以在运行时(runtime)给已存在的对象添加额外的方法:
s = new Person("Simon", "Willison"); s.firstNameCaps(); // TypeError on line 1: s.firstNameCaps is not a function Person.prototype.firstNameCaps = function() { return this.first.toUpperCase() } s.firstNameCaps(); // SIMON
new与构造函数(结合this)
实现一个和 new
关键字有类似效果的 trivial
方法:
- 下面是一个
new
方法的简单实现:
function trivialNew(constructor, ...args) { var o = {}; // 创建一个对象 constructor.apply(o, args); return o; }
note:
这并不是 new
的完整实现,因为它没有创建原型(prototype)链。
(想举例说明 new 的实现有些困难)l因为你不会经常用到这个,但是适当了解一下还是很有用的。
在这一小段代码里,...args
(包括省略号)叫作剩余参数(rest arguments)。如名所示,这个东西包含了剩下的参数。
因此,调用
var bill = trivialNew(Person, "William", "Orange");
可认为和调用如下语句是等效的
var bill = new Person("William", "Orange");
this
关键字 this
。当使用在函数中时,this 指代当前的对象,也就是 调用了函数的对象
。
如果在一个对象上使用 点或者方括号
来访问属性或方法,这个对象就成了 this。
否则, this 将指向全局对象(global object)。这是一个经常出错的地方。
使用关键字 this
改进已有的 makePerson
函数:
function Person(first, last) { this.first = first; this.last = last; this.fullName = function() { return this.first + ' ' + this.last; } this.fullNameReversed = function() { return this.last + ', ' + this.first; } } var s = new Person("Simon", "Willison");
我们引入了另外一个关键字:new
,它和 this
密切相关。
它(new
)的作用是创建一个崭新的 空对象{}
,然后使用指向那个对象的 this
调用特定的函数。
注意,含有 this
的特定函数不会返回任何值,只会修改 this
对象本身。
new
关键字将生成的 this
对象返回给调用方,而被 new
调用的函数称为构造函数。(是的,只是某个函数被new调用了,那么被调用的函数就叫构造函数;但是一般的,我们会让new调用一个适合用来创建的对象的函数,习惯上,这样的被设计为初始化对象的函数首字母大写,这样用new 调用他们的时候就容易识别了)
指定this(对象)来调用基于该this对象的面向对象的方法
- 用对象
obj.FunctionName()
或obj[FunctionName]()
的行形式调用,方法中的this指的就是obj - 用函数对象的
apply()
:FunctionName.apply(thisArg,argArray)
- 用函数对象的
call()
:FunctionName.call(thisArg,argList)
call()
知道了 new
和 this
的基本特点和工作原理后,我们看一下 call()
是
function Product(name, price) { this.name = name; this.price = price; } function Food(name, price) { Product.call(this, name, price); this.category = 'food'; } console.log(new Food('cheese', 5));//Food { name: 'cheese', price: 5, category: 'food' } console.log(new Food('cheese', 5).name);// expected output: "cheese" console.log((new Food('cheese', 5)).name);//the same as `new Food('cheese',5).name` console.log(Food('cheese', 5));//expected undefined // console.log(new (Food('cheese',5).name));// Wrong! TypeError // console.log(Food('Cheese',5).name);//Wrong! TypeError console.log();
这里,
<strong>
call()</strong>
方法使用 一个指定的 this
值和 单独给出的一个或多个参数
来 调用一个函数
。
注意: 该方法的语法和作用与 apply()
方法类似,只有一个区别,就是 call()
方法接受的是一个参数列表 ,而 apply()
方法接受的是一个包含多个参数的数组 。
对于本例代码,的new调用处,创建了一个空对象,然后用该空对象的this去调用函数Food(),Food()将会对这个空对象进行处理,Food()内部调用了Product函数对象的call()方法,该方法将空对象作为this实参,后面的name,price参数列表将传递给Product()函数,这样函数Product所作用于的对象this就是new出来的空对象的this.
new还将生成的this对象返回给调用方(本例的测试中对这个new 所调用的构造函数修饰后的this对象调用(访问)了其name属性.
new 小结
总之,new 是基于新建一个空对象 {}
的基础上执行一些操作
apply()
call()
中的例子用apply()来改写:
function Food(name, price) { Product.apply(this, [name, price]); this.category = 'food'; }
ES6种对象相关的特性
obj = { d: console.log, name: "NameInObj", data: { name: "nameIndataOfobj", age: 18 }, methodInObj: function () { console.log(this.data.name); console.log(this.data.age); this.d(this.data); // console.log(name); }, /* 定义函数的若干种方式: */ m1: function () { console.log("I am the method1😎"); }, /* 简化写法m1:将`:function`省略掉 */ m2() { console.log("I am the method2❤️"); } , /* 测试箭头函数的对象绑定特性 */ testThis() { const that = this; setTimeout( function () { console.log(this.name + " 😎test this within setTimeOut(expected undefined)"); } ); setTimeout( function () { console.log(that.name + " 😎test this within setTimeOut(expected name in obj)"); } ); setTimeout(() => { console.log(this.name + ` 👌test that within settimeOut(expected name in obj) `); }, 0); } }; function testmethod() { obj.methodInObj; obj.methodInObj(); console.log(obj.methods); } // console.log(obj.methods()); // console.log(obj); function testMn() { obj.m1(); obj.m2(); } // testMn() obj.testThis();
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了