norfish / blog Goto Github PK
View Code? Open in Web Editor NEW个人博客
Home Page: http://norfish.github.io
个人博客
Home Page: http://norfish.github.io
我觉得自己最近越来越懒散了,可能是因为「winter is comming」。
借了一本书,准备这周内看完,现在才刚看了个序。
本来准备20号把 mustache 源码读完,顺便写篇博客。但截止到今天,刚80%,博客还没影。
话说最近在做测试,发现了测试时候的一些痛点,想解决掉。可是确迟迟没能下手。
好多好多的事情,其实到了现在,竟然一个还没成。现在只能假装很忙的样子在公司加班,还忙里偷闲,想写点儿东西。又一次陷入了拖延症的怪圈。谁让我一不小心吃了公司的加班餐呢!自作孽,不可活。
下面咱们来说说成功学吧。我记得很小的时候我就很瘦,很弱小,还经常生病。所以我就特别希望能成为一个肌肉男,最起码也得是个死胖子。而我堂哥,那时候可是标准的肌肉男,他可以单手把我拎起来,就像拎小鸡一样。这让我一度很苦恼,于是我就发奋要成为一个像他那么健壮的男子。那时候,他经常锻炼,每天要举一个很重的杠铃。于是,我也举,每天都举。就这样居然也坚持了两个多月。但我还是很瘦,还是很弱小,经常生病。
那时候老师常教育我们凡事要坚持,只要坚持就能成功,只能努力就一定有收获。可是我还是那个我,身体并没有变强壮。也许你会说,肯定是我坚持的还不够久。好吧,我只想说,郭敬明就算再努力去增高,也到不了姚明的胳肢窝。这就是差别,不是努力所能弥补的。有些事情,明知山有虎,就别再**似的还向虎山行了,你又不是武松。
很多事情,不是努力就能有结果的。所以最重要的就是了解自己,了解你所做的事。是否值得,生命只有一次,没有必要去浪费太多的经历去做一件你就算很努力去做,也可能没别人随便做做好的事情上。 认清自己,知其不可为而为之,那是勇气,也是愚蠢。你的明知徒劳的努力,可能只是为了让自己觉得不后悔而已,但是那又能有什么卵用。这和阿Q的那套理论又有什么差别。「虽然失败了,但至少我曾经为它努力奋斗过」,不过是自我感动而已。永远不要跟天才比天赋,也不要跟**比下限。
看到过一句话,我觉得竟很有道理。「这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。」———By于宙.《我们这一代人的困惑》
看个例子吧:
#!/bin/sh
cd ~
mkdir shell_tut
cd shell_tut
for ((i=0; i<10; i++)); do
touch test_$i.txt
done
cd, mkdir, touch都是系统自带的程序,一般在/bin或者/usr/bin目录下。for, do, done是sh脚本语言的关键字。
shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。Ken Thompson的sh是第一种Unix Shell,Windows Explorer是一个典型的图形界面Shell。
shell脚本(shell script),是一种为shell编写的脚本程序。业界所说的shell通常都是指shell脚本,但读者朋友要知道,shell和shell script是两个不同的概念。由于习惯的原因,简洁起见,本文出现的“shell编程”都是指shell脚本编程,不是指开发shell自身(如Windows Explorer扩展开发)。
shell编程跟java、php编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
当前主流的操作系统都支持shell编程,本文档所述的shell编程是指Linux下的shell,讲的基本都是POSIX标准下的功能,所以,也适用于Unix及BSD(如Mac OS)。
Linux默认安装就带了shell解释器。
Mac OS不仅带了sh、bash这两个最基础的解释器,还内置了ksh、csh、zsh等不常用的解释器。
windows出厂时没有内置shell解释器,需要自行安装,为了同时能用grep, awk, curl等工具,最好装一个cygwin或者mingw来模拟linux环境。
即Bourne shell,POSIX(Portable Operating System Interface)标准的shell解释器,它的二进制文件路径通常是/bin/sh,由Bell Labs开发。
本文讲的是sh,如果你使用其它语言用作shell编程,请自行参考相应语言的文档。
Bash是Bourne shell的替代品,属GNU Project,二进制文件路径通常是/bin/bash。业界通常混用bash、sh、和shell,比如你会经常在招聘运维工程师的文案中见到:熟悉Linux Bash编程,精通Shell编程。
在CentOS里,/bin/sh是一个指向/bin/bash的符号链接:
[root@centosraw ~]# ls -l /bin/*sh
-rwxr-xr-x. 1 root root 903272 Feb 22 05:09 /bin/bash
-rwxr-xr-x. 1 root root 106216 Oct 17 2012 /bin/dash
lrwxrwxrwx. 1 root root 4 Mar 22 10:22 /bin/sh -> bash
但在Mac OS上不是,/bin/sh和/bin/bash是两个不同的文件,尽管它们的大小只相差100字节左右:
iMac:~ wuxiao$ ls -l /bin/*sh
-r-xr-xr-x 1 root wheel 1371648 6 Nov 16:52 /bin/bash
-rwxr-xr-x 2 root wheel 772992 6 Nov 16:52 /bin/csh
-r-xr-xr-x 1 root wheel 2180736 6 Nov 16:52 /bin/ksh
-r-xr-xr-x 1 root wheel 1371712 6 Nov 16:52 /bin/sh
-rwxr-xr-x 2 root wheel 772992 6 Nov 16:52 /bin/tcsh
-rwxr-xr-x 1 root wheel 1103984 6 Nov 16:52 /bin/zsh
理论上讲,只要一门语言提供了解释器(而不仅是编译器),这门语言就可以胜任脚本编程,常见的解释型语言都是可以用作脚本编程的,如:Perl、Tcl、Python、PHP、Ruby。Perl是最老牌的脚本编程语言了,Python这些年也成了一些linux发行版的预置解释器。
编译型语言,只要有解释器,也可以用作脚本编程,如C shell是内置的(/bin/csh),Java有第三方解释器Jshell,Ada有收费的解释器AdaScript。
如下是一个PHP Shell Script示例(假设文件名叫test.php):
#!/usr/bin/php
<?php
for ($i=0; $i < 10; $i++)
echo $i . "\n";
执行:
/usr/bin/php test.php
或者:
chmod +x test.php
./test.php
如果你已经掌握了一门编程语言(如PHP、Python、Java、JavaScript),建议你就直接使用这门语言编写脚本程序,虽然某些地方会有点啰嗦,但你能利用在这门语言领域里的经验(单元测试、单步调试、IDE、第三方类库)。
新增的学习成本很小,只要学会怎么使用shell解释器(Jshell、AdaScript)就可以了。
如果你觉得自己熟悉的语言(如Java、C)写shell脚本实在太啰嗦,你只是想做一些备份文件、安装软件、下载数据之类的事情,学着使用sh,bash会是一个好主意。
shell只定义了一个非常简单的编程语言,所以,如果你的脚本程序复杂度较高,或者要操作的数据结构比较复杂,那么还是应该使用Python、Perl这样的脚本语言,或者是你本来就已经很擅长的高级语言。因为sh和bash在这方面很弱,比如说:
如果你的脚本是提供给别的用户使用,使用sh或者bash,你的脚本将具有最好的环境兼容性,perl很早就是linux标配了,python这些年也成了一些linux发行版的标配,至于mac os,它默认安装了perl、python、ruby、php、java等主流编程语言。
打开文本编辑器,新建一个文件,扩展名为sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好,如果你用php写shell 脚本,扩展名就用php好了。
输入一些代码,第一行一般是这样:
#!/bin/bash
#!/usr/bin/php
“#!”是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行。
运行Shell脚本有两种方法:
chmod +x test.sh
./test.sh
注意,一定要写成./test.sh,而不是test.sh,运行其它二进制的程序也一样,直接写test.sh,linux系统会去PATH里寻找有没有叫test.sh的,而只有/bin, /sbin, /usr/bin,/usr/sbin等在PATH里,你的当前目录通常不在PATH里,所以写成test.sh是会找不到命令的,要用./test.sh告诉系统说,就在当前目录找。
通过这种方式运行bash脚本,第一行一定要写对,好让系统查找到正确的解释器。
这里的"系统",其实就是shell这个应用程序(想象一下Windows Explorer),但我故意写成系统,是方便理解,既然这个系统就是指shell,那么一个使用/bin/sh作为解释器的脚本是不是可以省去第一行呢?是的。
这种运行方式是,直接运行解释器,其参数就是shell脚本的文件名,如:
/bin/sh test.sh
/bin/php test.php
这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。
定义变量时,变量名不加美元符号($),如:
your_name="qinjx"
注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。
除了显式地直接赋值,还可以用语句给变量赋值,如:
for file in `ls /etc`
使用一个定义过的变量,只要在变量名前面加美元符号即可,如:
your_name="qinjx"
echo $your_name
echo ${your_name}
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:
for skill in Ada Coffe Action Java do
echo "I am good at ${skill}Script"
done
如果不给skill变量加花括号,写成echo "I am good at $skillScript",解释器就会把$skillScript当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。
推荐给所有变量加上花括号,这是个好的编程习惯。IntelliJ IDEA编写shell script时,IDE就会提示加花括号。
已定义的变量,可以被重新定义,如:
your_name="qinjx"
echo $your_name
your_name="alibaba"
echo $your_name
这样写是合法的,但注意,第二次赋值的时候不能写$your_name="alibaba",使用变量的时候才加美元符。
以“#”开头的行就是注释,会被解释器忽略。
sh里没有多行注释,只能每一行加一个#号。就像这样:
#--------------------------------------------
# 这是一个自动打ipa的脚本,基于webfrogs的ipa-build书写:https://github.com/webfrogs/xcode_shell/blob/master/ipa-build
# 功能:自动为etao ios app打包,产出物为14个渠道的ipa包
# 特色:全自动打包,不需要输入任何参数
#--------------------------------------------
##### 用户配置区 开始 #####
#
#
# 项目根目录,推荐将此脚本放在项目的根目录,这里就不用改了
# 应用名,确保和Xcode里Product下的target_name.app名字一致
#
##### 用户配置区 结束 #####
如果在开发过程中,遇到大段的代码需要临时注释起来,过一会儿又取消注释,怎么办呢?每一行加个#符号太费力了,可以把这一段要注释的代码用一对花括号括起来,定义成一个函数,没有地方调用这个函数,这块代码就不会执行,达到了和注释一样的效果。
字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了,哈哈),字符串可以用单引号,也可以用双引号,也可以不用引号。单双引号的区别跟PHP类似。
str='this is a string'
单引号字符串的限制:
your_name='qinjx'
str="Hello, I know your are \"$your_name\"! \n"
your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
string="abcd"
echo ${#string} #输出:4
string="alibaba is a great company"
echo ${string:1:4} #输出:liba
string="alibaba is a great company"
echo `expr index "$string" is`#输出:8,这个语句的意思是:找出单词is在这名话中的位置
参见本文档末尾的参考资料中Advanced Bash-Scripting Guid Chapter 10.1
和Java、PHP等语言不一样,sh的流程控制不可为空,如:
<?php
if (isset($_GET["q"])) {
search(q);
}
else {
//do nothing
}
在sh/bash里可不能这么写,如果else分支没有语句执行,就不要写这个else。
还要注意,sh里的if [ $foo -eq 0 ],这个方括号跟Java/PHP里if后面的圆括号大不相同,它是一个可执行程序(和cd, ls, grep一样),相不到吧?在CentOS上,它在/usr/bin目录下:
ll /usr/bin/[
-rwxr-xr-x. 1 root root 33408 6月 22 2012 /usr/bin/[
正因为方括号在这里是一个可执行程序,方括号后面必须加空格,不能写成if [$foo -eq 0]
if condition
then
command1
command2
...
commandN
fi
写成一行(适用于终端命令提示符):
if `ps -ef | grep ssh`; then echo hello; fi
末尾的fi就是if倒过来拼写,后面还会遇到类似的
if condition
then
command1
command2
...
commandN
else
command
fi
if condition1
then
command1
elif condition2
command2
else
commandN
fi
在开篇的示例里演示过了:
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
写成一行:
for var in item1 item2 ... itemN; do command1; command2… done;
for (( EXP1; EXP2; EXP3 ))
do
command1
command2
command3
done
while condition
do
command
done
while :
do
command
done
或者
while true
do
command
done
或者
for (( ; ; ))
until condition
do
command
done
case "${opt}" in
"Install-Puppet-Server" )
install_master $1
exit
;;
"Install-Puppet-Client" )
install_client $1
exit
;;
"Config-Puppet-Server" )
config_puppet_master
exit
;;
"Config-Puppet-Client" )
config_puppet_client
exit
;;
"Exit" )
exit
;;
* ) echo "Bad option, please choose again"
esac
case的语法和C family语言差别很大,它需要一个esac(就是case反过来)作为结束标记,每个case分支用右圆括号,用两个分号表示break
可以使用source和.关键字,如:
source ./function.sh
. ./function.sh
在bash里,source和.是等效的,他们都是读入function.sh的内容并执行其内容(类似PHP里的include),为了更好的可移植性,推荐使用第二种写法。
包含一个文件和在执行一个文件一样,也要写这个文件的路径,不能光写文件名,比如上述例子中:
. ./function.sh
不可以写作:
. function.sh
如果function.sh是用户传入的参数,如何获得它的绝对路径呢?方法是:
real_path=`readlink -f $1`#$1是用户输入的参数,如function.sh
. $real_path
sh脚本结合系统命令便有了强大的威力,在字符处理领域,有grep、awk、sed三剑客,grep负责找出特定的行,awk能将行拆分成多个字段,sed则可以实现更新插入删除等写操作。
查看进程列表
作为一门被长期误解的编程语言,javascript一直被人所诟病.但是如果你真正的了解它之后,你会深深的爱上它.
首先,javascript是一个面向对象的编程语言,而且是一个纯粹的面向对象.虽然很多人不能理解,因为在他们眼中,只有像java,c++这样的编程语言才能称之为面向对象.但是,我只想说,你误解我,是因为你不懂我.
JavaScrip秘密花园在JavaScrip中,一切变量皆对象,除了两个特殊值undefined 和 null.
什么是面向对象?
以这三点做为依据,C++ 是半面向对象半面向过程语言,因为,虽然他实现了类的封装、继承和多态,但存在非对象性质的全局函数和变量。Java、C# 是完全的面向对象语言,它们通过类的形式组织函数和变量,使之不能脱离对象存在。但这里函数本身是一个过程,只是依附在某个类上。
然而,面向对象仅仅是一个概念或者编程**而已,它不应该依赖于某个语言存在。比如 Java 采用面向对象**构造其语言,它实现了类、继承、派生、多态、接口等机制。但是这些机制,只是实现面向对象编程的一种手段,而非必须。换言之,一门语言可以根据其自身特性选择合适的方式来实现面向对象。所以,由于大多数程序员首先学习或者使用的是类似 Java、C++ 等高级编译型语言(Java 虽然是半编译半解释,但一般做为编译型来讲解),因而先入为主地接受了“类”这个面向对象实现方式,从而在学习脚本语言的时候,习惯性地用类式面向对象语言中的概念来判断该语言是否是面向对象语言,或者是否具备面向对象特性。这也是阻碍程序员深入学习并掌握 JavaScript 的重要原因之一。
实际上,JavaScript语言是通过一种叫做原型(prototype)的方式来实现面向对象编程的。它和其他的面向对象类编程语言一样,只是它的实现方式不同而已,或者说他们采用了不同的面向对象设计哲学。
在基于类的面向对象方式中,对象(object)依靠类(class)来产生。而在基于原型的面向对象方式中,对象(object)则是依靠 构造器(constructor)利用 原型(prototype)构造出来的。
举个客观世界的例子来说明二种方式认知的差异。例如工厂造一辆车,一方面,工人必须参照一张工程图纸,设计规定这辆车应该如何制造。这里的工程图纸就好比是语言中的 类 (class),而车就是按照这个 类(class)制造出来的;另一方面,工人和机器 ( 相当于 constructor)利用各种零部件如发动机,轮胎,方向盘 ( 相当于 prototype 的各个属性 ) 将汽车构造出来。
在这里我不想讨论太多这两种面向对象究竟孰优孰劣的问题,这个讨论来讨论去也不会有定论.但是以为个人观点我更倾向于基于原型的面向对象.因为一切事物皆对象.现实世界中的所有对象也都是由其他对象构造出来的,而紧紧依靠图纸是没法产生一个现实中的汽车的.这个设计更符合现实世界的客观规律.
JavaScript的面向对象来源于‘self’这个牛逼但短命的编程语言。
Self语言把概念上的精简作为设计原则。它取消了类的概念,只有对象的概念,同时把消息作为最基本的操作。把对象的属性理解为获取或更改属性这两种方法,从而把属性的概念简化为方法;取消了变量和赋值,并以通过消息来读槽和写槽的方式代之。
在 JavaScript 中,prototype 是函数的一个属性,同时也是由构造函数创建的对象的一个属性。 函数的原型为对象。 它主要在函数用作构造函数时使用。
在编程语言中,目前存在两种继承方式:类继承和原型继承.
而由于java等主流编程语言的支持使得类继承被大众所普遍接受
要理解原型继承,首先得先熟悉几个概念,咱们一步步说起:
-1.声明对象直接量:JSON
var obj = {
name: "jack",
eat: "bread"
}
console.log(typeof obj);
-2.使用构造函数生成一个新的对象
//构造函数
var Foo = function(name){
this.name = name; //私有属性
}
//原型方法和属性,被继承时候才会调用
Foo.prototype.run = function(){
alert("I'm running so fast that can't stop at all!");
}
var kick = new Foo("kick");
console.log(typeof kick);
console.log(kick.name);
kick.run();
-3.使用使用Object.create创建对象
ECMAScript 5中引入了一个新方法: Object.create. 可以调用这个方法来创建一个新对象. 新对象的原型就是调用create方法时传入的第一个参数:
先来看一下create方法是如何实现的,该方法来源于Douglas Crockford,现在已被ECMAScript 5引入:
Object.create = function (parent) {
function F() {}
F.prototype = parent;
return new F();
};
这个看起来很简洁,而且能够完全代替new的用法,毕竟new关键字并不真正的属于JavaScrip的原型模式.它先是声明了一个构造器,然后将其原型设置为你想要的值,最后返回生成的新对象.其实就是封装了new.
下面这段代码就是真正的原型继承了.look:
var Point = {
x: 0,
y: 0,
print: function () { console.log(this.x, this.y); }
};
var p = Object.create(Point); //new一个对象
p.x = 10;
p.y = 20;
p.print(); // 10 20
code:
function Plant(name,year){
this.name = name;
this.year = year || 0;
}
var tree.prototype = new Plant('tree');
tree.prototype.grow = function(){
this.year ++;
}
tree.prototype.old = functiono(){
console.log(this.year);
}
上面这段代码使用原型实现了一个简单的对象继承.下面来分析下上面这段代码
首先是声明了一个构造函数,构造函数和普通函数有什么区别?构造函数可以使用new调用,生成一个新的对象.
如果想要在对象上添加方法,可以将方法写在对象的原型上.
子类继承父类,只需要把父对象复制给自对象的原型上即可.
下面这段是ECMAScript关于原型的解释
ECMAScript does not contain proper classes such as those in C++, Smalltalk, or Java, but rather, supports constructors which create objects by executing code that allocates storage for the objects and initialises all or part of them by assigning initial values to their properties. All constructors are objects, but not all objects are constructors. Each constructor has a Prototype property that is used to implement prototype-based inheritance and shared properties. Objects are created by using constructors in new expressions; for example, new String("A String") creates a new String object. Invoking a constructor without using new has consequences that depend on the constructor. For example, String("A String") produces a primitive string, not an object.
ECMAScript supports prototype-based inheritance. Every constructor has an associated prototype, and every object created by that constructor has an implicit reference to the prototype (called the object's prototype) associated with its constructor. Furthermore, a prototype may have a non-null implicit reference to its prototype, and so on; this is called the prototype chain. When a reference is made to a property in an object, that reference is to the property of that name in the first object in the prototype chain that contains a property of that name. In other words, first the object mentioned directly is examined for such a property; if that object contains the named property, that is the property to which the reference refers; if that object does not contain the named property, the prototype for that object is examined next; and so on.
依据我的理解就是说:
JavaScrip可以采用构造器(constructor)生成一个新的对象,每个构造器都拥有一个prototype属性,而每个通过此构造器生成的对象都有一个指向该构造器原型(prototype)的内部私有的链接(proto),而这个prototype因为是个对象,它也拥有自己的原型,这么一级一级指导原型为null,这就构成了原型链.
这里我们涉及到了一个隐匿属性proto**,那么proto和prototype究竟有什么区别嘞?**
注: proto 是一个不应在你代码中出现的非正规的用法,这里仅仅用它来解释JavaScript原型继承的工作原理。
知道了JavaScrip原型链的存在之后,让我们来看下它的实现,下面这段代码展示了原型链是如何工作的.
function getProperty(obj, prop) {
if (obj.hasOwnProperty(prop)) //首先查找自身属性,如果有则直接返回
return obj[prop]
else if (obj.__proto__ !== null)
return getProperty(obj.__proto__, prop) //如何不是私有属性,就在原型链上一步步向上查找,直到找到,如果找不到就返回undefind
else
return undefined
}
So,如果proto可以使用的话,我们可以通过下面这种方式实现继承:
var person = {
city: "Beijing",
hate: function(){
alert("I really hate the PM2.5 and the foggy wether!");
}
}
var lee = {
name: "lee",
age: "18",
__proto__: person
}
console.log(lee);
lee.hate();
这都什么玩意儿,不是要用new吗.事实上,事情不是这么简单滴, 为了和主流的类继承扯上那么一点儿关系,JavaScrip引入了'new'关键字,引入了构造函数.所以通常我们看到的是下面这样的:
var Person = function(name,age){
this.name = name;
this.age = age;
};
Person.prototype = {
city: "Beijing",
hate: function(){
alert("I really hate the PM2.5 and the foggy wether!");
}
}
var lee = new Person('lee',18);
console.log(lee.name);
lee.hate();
我们需要一个像类一样的东西,于是有了构造函数,我们得有一个通过类生成实例的过程,于是又出现了new.这么一来JavaScrip的原型继承似乎就变得不伦不类了.虽然JavaScrip的原型继承来源于'self',但是却追随了类继承的形式.罪过,不过话说回来,也许就是因为这种妥协才让JavaScrip能够流行起来,并成为了现在最流行的原型继承语言,而self,说实话,它独特写法确实挺难让人接受的.
var Foo = function(){
this.name = "foo";
}
Foo.prototype.say = function(){
alert("Hello World!");
}
var foo = new Foo();
console.log(foo.__proto__); //私有链接,指向构造函数的原型
console.log(Foo.prototype);
console.log(foo.__proto__ === Foo.prototype); //true
console.log(foo.__proto__.constructor === Foo); //true
// 声明 Animal 对象构造器
function Animal(name) {
this.name = name;
}
// 将 Animal 的 prototype 属性指向一个对象,
// 亦可直接理解为指定 Animal 对象的原型
Animal.prototype = {
weight: 0,
eat: function() {
alert( "Animal is eating!" );
}
}
// 声明 Mammal 对象构造器
function Mammal() {
this.name = "mammal";
}
// 指定 Mammal 对象的原型为一个 Animal 对象。
// 实际上此处便是在创建 Mammal 对象和 Animal 对象之间的原型链
Mammal.prototype = new Animal("animal");
// 声明 Horse 对象构造器
function Horse( height, weight ) {
this.name = "horse";
this.height = height;
this.weight = weight;
}
// 将 Horse 对象的原型指定为一个 Mamal 对象,继续构建 Horse 与 Mammal 之间的原型链
Horse.prototype = new Mammal();
// 重新指定 eat 方法 , 此方法将覆盖从 Animal 原型继承过来的 eat 方法
Horse.prototype.eat = function() {
alert( "Horse is eating grass!" );
}
// 验证并理解原型链
var horse = new Horse( 100, 300 );
console.log( horse.__proto__ === Horse.prototype );
console.log( Horse.prototype.__proto__ === Mammal.prototype );
console.log( Mammal.prototype.__proto__ === Animal.prototype );
//原型链
Horse-->Mammal的实例
Mammal-->Animal的实例
Animal -->Object.prototype
在 ECMAScript 中,每个由构造器创建的对象拥有一个指向构造器 prototype 属性值的 隐式引用(implicit reference),这个引用称之为 原型(prototype)。进一步,每个原型可以拥有指向自己原型的 隐式引用(即该原型的原型),如此下去,这就是所谓的 原型链(prototype chain) 参考资源。在具体的语言实现中,每个对象都有一个 proto 属性来实现对原型的 隐式引用。
我们已经了解了JS原型继承是什么,以及JS如何用特定的方式来实现之。然而使用真正的原型继承(如 Object.create 以及 proto)还是存在以下缺点:
到了这里我们基本对JavaScrip的原型继承有了一个更深层的认识了.通过历史回溯我们也了解了为什么JavaScrip会变成现在这个不伦不类的样子.
JavaScrip是一个完全的面向对象函数式编程语言,采用原型继承,虽然写法类似类继承.但是我们不能因此就认为它不是面向对象的编程语言.而且nodejs的出现,又让JavaScrip在编程语言界火了一把.所以是时候拥抱JavaScrip了.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.